OpenASIP 2.2
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
DataDependenceGraphBuilder Class Reference

#include <DataDependenceGraphBuilder.hh>

Inheritance diagram for DataDependenceGraphBuilder:
Inheritance graph
Collaboration diagram for DataDependenceGraphBuilder:
Collaboration graph

Classes

struct  BBData
 

Public Member Functions

 DataDependenceGraphBuilder ()
 
 DataDependenceGraphBuilder (InterPassData &ipd)
 
virtual ~DataDependenceGraphBuilder ()
 
void addAliasAnalyzer (MemoryAliasAnalyzer *analyzer)
 
virtual DataDependenceGraphbuild (ControlFlowGraph &cGraph, DataDependenceGraph::AntidependenceLevel antidependenceLevel, const TTAMachine::Machine &mach, const UniversalMachine *um=NULL, bool createMemAndFUDeps=true, bool createDeathInformation=true, llvm::AliasAnalysis *AA=NULL)
 
virtual DataDependenceGraphbuild (TTAProgram::BasicBlock &bb, DataDependenceGraph::AntidependenceLevel antidependenceLevel, const TTAMachine::Machine &mach, const TCEString &ddgname="small bb", const UniversalMachine *um=NULL, bool createMemAndFUDeps=true, llvm::AliasAnalysis *AA=NULL)
 

Protected Types

enum  BBState { BB_UNREACHED = 0 , BB_QUEUED , BB_READY , BB_STATES }
 
enum  ConstructionPhase { REGISTERS_AND_PROGRAM_OPERATIONS = 0 , MEMORY_AND_SIDE_EFFECTS }
 
typedef ControlFlowGraph::NodeSet BasicBlockNodeSet
 
typedef DataDependenceGraph::NodeSet MNodeSet
 
typedef LiveRangeData::MoveNodeUseSet MoveNodeUseSet
 
typedef LiveRangeData::MoveNodeUseMapSet MoveNodeUseMapSet
 
typedef LiveRangeData::MoveNodeUseMap MoveNodeUseMap
 
typedef LiveRangeData::MoveNodeUseSetPair MoveNodeUseSetPair
 
typedef LiveRangeData::MoveNodeUsePair MoveNodeUsePair
 
typedef std::map< int, TCEStringSpecialRegisters
 
typedef std::vector< MemoryAliasAnalyzer * > AliasAnalyzerVector
 
typedef std::map< BasicBlockNode *, BBData * > BBDataMap
 
typedef std::list< BBData * > BBDataList
 

Protected Member Functions

bool isTriggering (const MoveNode &mn)
 
void updatePreceedingRegistersUsedAfter (BBData &bbd, bool firstTime)
 
bool updateRegistersUsedInOrAfter (BBData &bbd)
 
bool updateRegistersAliveAfter (BBData &bbd)
 
bool updateMemAndFuAliveAfter (BBData &bbd)
 
void createMemAndFUstateDeps ()
 
void createRegisterDeps ()
 
void initializeBBStates ()
 
BasicBlockNodequeueFirstBB ()
 
void clearUnneededBookkeeping ()
 
void clearUnneededBookkeeping (TTAProgram::BasicBlock &bb, bool aliveInformationNeeded=true)
 
void iterateBBs (ConstructionPhase phase)
 
void searchRegisterDeaths ()
 
void iterateRegisterDeaths ()
 
void setSucceedingPredeps (BBData &bbd, bool queueAll, ConstructionPhase phase)
 
bool appendUseMapSets (const MoveNodeUseMapSet &srcMap, MoveNodeUseMapSet &dstMap, bool addLoopProperty)
 
void setSucceedingPredepsForBB (TTAProgram::BasicBlock &processedBB, BasicBlockNode &successor, bool queueAll, bool loop, ConstructionPhase phase)
 
void updateBB (BBData &bbd, ConstructionPhase phase)
 
void constructIndividualBB (ConstructionPhase phase)
 
void constructIndividualFromInlineAsmBB (ConstructionPhase phase)
 
void constructIndividualBB (BBData &bbd, ConstructionPhase)
 
void constructBB (BasicBlockNodeSet &inputBlocks)
 
void createOperationEdges (ProgramOperationPtr po)
 
void processGuard (MoveNode &moveNode)
 
void processSource (MoveNode &moveNode)
 
void processResultRead (MoveNode &moveNode)
 
void processCall (MoveNode &mn)
 
void processReturn (MoveNode &moveNode)
 
void processEntryNode (MoveNode &mn)
 
void processDestination (class MoveNode &moveNode, ConstructionPhase phase)
 
void processRegUse (MoveNodeUse mn, const TCEString &reg)
 
void updateMemUse (MoveNodeUse mnd, const TCEString &category)
 
void processRegWrite (MoveNodeUse mn, const TCEString &reg)
 
void updateMemWrite (MoveNodeUse mnd, const TCEString &category)
 
void processTriggerPO (class MoveNode &moveNode, Operation &dop)
 
void processTriggerRegistersAndOperations (MoveNode &moveNode, Operation &dop)
 
void processTriggerMemoryAndFUStates (MoveNode &moveNode, Operation &dop)
 
void createTriggerDependencies (class MoveNode &moveNode, class Operation &dop)
 
void createSideEffectEdges (MoveNodeUseSet &prevMoves, const MoveNode &mn, Operation &dop)
 
void processMemWrite (MoveNodeUse mnd)
 
void processMemUse (MoveNodeUse mnd)
 
void processOperand (class MoveNode &moveNode, Operation &dop)
 
MemoryAliasAnalyzer::AliasingResult analyzeMemoryAlias (const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)
 
bool isAddressTraceable (const ProgramOperation &pop)
 
TCEString memoryCategory (const MoveNodeUse &mnd)
 
bool checkAndCreateMemDep (MoveNodeUse prev, MoveNodeUse mnd, DataDependenceEdge::DependenceType depType)
 
void checkAndCreateMemAntideps (MoveNodeUse &mnd, std::set< MoveNodeUse > &prevNodes, DataDependenceEdge::DependenceType depType, bool traceable)
 
bool hasEarlierMemWriteToSameAddressWithSameGuard (MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
 
std::set< MoveNodeUseearlierWritesWithSameGuard (MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
 
bool hasEarlierWriteWithSameGuard (MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
 
void createRegisterAntideps (const TCEString &reg, MoveNodeUse &mnd, MoveNodeUseSet &predecessorNodes, DataDependenceEdge::DependenceType depType, bool guardedKillFound)
 
void changeState (BBData &bbd, BBState newState, bool priorize=false)
 
bool isAlwaysDifferentFU (const MoveNode *srcMN, const MoveNode *dstMN)
 
void findStaticRegisters (TTAProgram::CodeSnippet &cs, std::map< int, TCEString > &registers)
 find special register data from old frontend code
 
void findStaticRegisters (ControlFlowGraph &cfg, std::map< int, TCEString > &registers)
 
void findStaticRegisters (TTAProgram::Instruction &ins, std::map< int, TCEString > &registers)
 
void findStaticRegisters (const UniversalMachine &um, std::map< int, TCEString > &registers)
 
void appendMoveNodeUse (const LiveRangeData::MoveNodeUseSet &src, LiveRangeData::MoveNodeUseSet &dst, bool setLoopProperty)
 

Protected Attributes

std::set< TCEStringallParamRegs_
 
BBDataList blocksByState_ [BB_STATES]
 
BBDataMap bbData_
 
BasicBlockNodecurrentBB_
 
BBDatacurrentData_
 
DataDependenceGraphcurrentDDG_
 
AliasAnalyzerVector aliasAnalyzers_
 
SpecialRegisters specialRegisters_
 contains stack pointer, RV and parameter registers.
 
InterPassDatainterPassData_
 
ControlFlowGraphcfg_
 
bool rvIsParamReg_
 
const TTAMachine::Machinemach_
 

Static Protected Attributes

static const TCEString RA_NAME = "RA"
 

Detailed Description

DataDependenceGraphBuilder class is responsible for building data dependence graphs.

Definition at line 70 of file DataDependenceGraphBuilder.hh.

Member Typedef Documentation

◆ AliasAnalyzerVector

Definition at line 112 of file DataDependenceGraphBuilder.hh.

◆ BasicBlockNodeSet

Definition at line 102 of file DataDependenceGraphBuilder.hh.

◆ BBDataList

typedef std::list<BBData*> DataDependenceGraphBuilder::BBDataList
protected

Definition at line 144 of file DataDependenceGraphBuilder.hh.

◆ BBDataMap

Definition at line 143 of file DataDependenceGraphBuilder.hh.

◆ MNodeSet

Definition at line 103 of file DataDependenceGraphBuilder.hh.

◆ MoveNodeUseMap

Definition at line 107 of file DataDependenceGraphBuilder.hh.

◆ MoveNodeUseMapSet

Definition at line 106 of file DataDependenceGraphBuilder.hh.

◆ MoveNodeUsePair

Definition at line 109 of file DataDependenceGraphBuilder.hh.

◆ MoveNodeUseSet

Definition at line 105 of file DataDependenceGraphBuilder.hh.

◆ MoveNodeUseSetPair

Definition at line 108 of file DataDependenceGraphBuilder.hh.

◆ SpecialRegisters

typedef std::map<int, TCEString> DataDependenceGraphBuilder::SpecialRegisters
protected

Definition at line 111 of file DataDependenceGraphBuilder.hh.

Member Enumeration Documentation

◆ BBState

Enumerator
BB_UNREACHED 
BB_QUEUED 

Basic block we have not yet encountered.

BB_READY 

BB which is queued to be processed.

BB_STATES 

BB which is already processed and is not queued.

Definition at line 114 of file DataDependenceGraphBuilder.hh.

114 {
115 BB_UNREACHED = 0, /// Basic block we have not yet encountered.
116 BB_QUEUED, /// BB which is queued to be processed
117 BB_READY, ///BB which is already processed and is not queued.
118 BB_STATES};
@ BB_STATES
BB which is already processed and is not queued.
@ BB_QUEUED
Basic block we have not yet encountered.
@ BB_READY
BB which is queued to be processed.

◆ ConstructionPhase

Enumerator
REGISTERS_AND_PROGRAM_OPERATIONS 
MEMORY_AND_SIDE_EFFECTS 

Definition at line 120 of file DataDependenceGraphBuilder.hh.

Constructor & Destructor Documentation

◆ DataDependenceGraphBuilder() [1/2]

POP_COMPILER_DIAGS DataDependenceGraphBuilder::DataDependenceGraphBuilder ( )

Constructor of Data Dependence graph builder.

This constructor does not take special registers from interpass data, so it must analyze them from the code annotations. Used with old frontend.

constant alias AA check aa between global variables.

Definition at line 118 of file DataDependenceGraphBuilder.cc.

118 :
119 interPassData_(NULL), cfg_(NULL), rvIsParamReg_(false) {
120
121 /// constant alias AA check aa between global variables.
123
124#ifdef USE_FALSE_AA
125 /// defining USE_FALSE_AA results in faster but
126 /// broken code. just for testing theoretical benefits.
128#endif
130
131 LLVMTCECmdLineOptions* llvmOptions =
132 dynamic_cast<LLVMTCECmdLineOptions*>(
134 if (llvmOptions != NULL && llvmOptions->disableLLVMAA() == false) {
136 }
137}
static CmdLineOptions * cmdLineOptions()
void addAliasAnalyzer(MemoryAliasAnalyzer *analyzer)
virtual bool disableLLVMAA() const

References addAliasAnalyzer(), Application::cmdLineOptions(), and LLVMTCECmdLineOptions::disableLLVMAA().

Here is the call graph for this function:

◆ DataDependenceGraphBuilder() [2/2]

DataDependenceGraphBuilder::DataDependenceGraphBuilder ( InterPassData ipd)

Constructor of Data Dependence graph builder.

This constructor takes special registers from interpass data.

Definition at line 145 of file DataDependenceGraphBuilder.cc.

145 :
146 // TODO: when param reg thing works, rvIsParamReg becomes true here
147 interPassData_(&ipd), cfg_(NULL), rvIsParamReg_(true) {
148
149 // Need to store data about special registers which have semantics
150 // between function calls and exits. These are stack pointer,
151 // return value register and the secondary "hi bits"
152 // return value register.
153
154 static const TCEString SP_DATUM = "STACK_POINTER";
155 static const TCEString FP_DATUM = "FRAME_POINTER";
156 static const TCEString RV_DATUM = "RV_REGISTER";
157 // high part of 64-bit return values.
158 static const TCEString RV_HIGH_DATUM = "RV_HIGH_REGISTER";
159
160 static const TCEString IPARAM_DATUM_PREFIX = "IPARAM";
161 static const TCEString VECTOR_RV_PREFIX="VRV_REGISTER";
162
164 dynamic_cast<SchedulerCmdLineOptions*>(
166
167 if (ipd.hasDatum(SP_DATUM)) {
168 RegDatum& sp = dynamic_cast<RegDatum&>(ipd.datum(SP_DATUM));
169 TCEString spName = sp.first + '.' + Conversion::toString(sp.second);
170 specialRegisters_[REG_SP] = spName;
171
172 // create stack alias analyzer if enabled.
173 if ((options != NULL && options->enableStackAA())) {
175 }
176
177 if (options != NULL && options->enableOffsetAA()) {
179 }
180
182
183 } else {
187 << "Warning: Stack pointer datum not found "
188 << "in interpassdata given to ddg builder. "
189 << "May generate invalid code if stack used."
190 << std::endl;
191 }
192 }
193
194 if (ipd.hasDatum(RV_DATUM)) {
195 RegDatum& rv = dynamic_cast<RegDatum&>(ipd.datum(RV_DATUM));
196 TCEString reg = rv.first + '.' + Conversion::toString(rv.second);
198 if (rvIsParamReg_) {
199 allParamRegs_.insert(reg);
200 }
201
202 } else {
206 << "Warning: Return value register datum not found "
207 << "in interpassdata given to ddg builder. "
208 << "May generate invalid code if return values used."
209 << std::endl;
210 }
211 }
212
213 for(int i = 2;;i++) {
214 TCEString datum = IPARAM_DATUM_PREFIX; datum << i;
215 if (ipd.hasDatum(datum)) {
216 RegDatum& p = dynamic_cast<RegDatum&>(ipd.datum(datum));
217 TCEString reg = p.first + '.' + Conversion::toString(p.second);
218 specialRegisters_[REG_IPARAM+i-1] = reg;
219 } else {
220 break;
221 }
222 }
223
224 for (int i = 0;;i++) {
225 TCEString datum = VECTOR_RV_PREFIX; datum << i;
226 if (ipd.hasDatum(datum)) {
227 RegDatum& p = dynamic_cast<RegDatum&>(ipd.datum(datum));
228 TCEString reg = p.first + '.' + Conversion::toString(p.second);
229 specialRegisters_[REG_VRV-i] = reg;
230 } else {
231 break;
232 }
233
234 }
235
236 if (ipd.hasDatum(FP_DATUM)) {
237 RegDatum& fp = dynamic_cast<RegDatum&>(ipd.datum(FP_DATUM));
238 TCEString reg = fp.first + '.' + Conversion::toString(fp.second);
240 } else {
244 << "Warning: Frame Pointer Register datum not found "
245 << "in interpassdata given to ddg builder. "
246 << "May generate invalid code."
247 << std::endl;
248 }
249 }
250
251 if (ipd.hasDatum(RV_HIGH_DATUM)) {
252 RegDatum& rvh = dynamic_cast<RegDatum&>(ipd.datum(RV_HIGH_DATUM));
254 rvh.first + '.' + Conversion::toString(rvh.second);
255 }
256
257 // constant alias AA check aa between global variables.
259
260 LLVMTCECmdLineOptions* llvmOptions =
261 dynamic_cast<LLVMTCECmdLineOptions*>(
263 if (llvmOptions != NULL && llvmOptions->disableLLVMAA() == false) {
265 }
267
268#ifdef USE_FALSE_AA
269 /// defining USE_FALSE_AA results in faster but
270 /// broken code. just for testing theoretical benefits.
272#else
273 if ((options != NULL && options->noaliasFunctions() &&
274 !options->noaliasFunctions()->empty())) {
275 addAliasAnalyzer(new FalseAliasAnalyzer(options->noaliasFunctions()));
276 }
277#endif
278}
static const int REG_SP
static const int REG_RV_HIGH
static const int REG_FP
static const int REG_RV
static const int REG_IPARAM
static const int REG_VRV
static MachInfoCmdLineOptions options
Definition MachInfo.cc:46
static const int VERBOSE_LEVEL_DEFAULT
Default verbose level - do not print anything unnecessary.
static int verboseLevel()
static std::ostream & logStream()
static std::string toString(const T &source)
SpecialRegisters specialRegisters_
contains stack pointer, RV and parameter registers.
bool hasDatum(const std::string &key) const
InterPassDatum & datum(const std::string &key)

References addAliasAnalyzer(), allParamRegs_, Application::cmdLineOptions(), InterPassData::datum(), LLVMTCECmdLineOptions::disableLLVMAA(), InterPassData::hasDatum(), Application::logStream(), options, REG_FP, REG_IPARAM, REG_RV, REG_RV_HIGH, REG_SP, REG_VRV, rvIsParamReg_, specialRegisters_, Conversion::toString(), Application::VERBOSE_LEVEL_DEFAULT, and Application::verboseLevel().

Here is the call graph for this function:

◆ ~DataDependenceGraphBuilder()

DataDependenceGraphBuilder::~DataDependenceGraphBuilder ( )
virtual

Destructor of DataDependenceGraphBuilder

Definition at line 283 of file DataDependenceGraphBuilder.cc.

283 {
285}
static void deleteAllItems(SequenceType &aSequence)

References aliasAnalyzers_, and SequenceTools::deleteAllItems().

Here is the call graph for this function:

Member Function Documentation

◆ addAliasAnalyzer()

void DataDependenceGraphBuilder::addAliasAnalyzer ( MemoryAliasAnalyzer analyzer)

Adds a memory alias analyzer to the DDG builder.

Parameters
analyzerobject which will analyze memory accesses.

Definition at line 293 of file DataDependenceGraphBuilder.cc.

293 {
294 aliasAnalyzers_.push_back(analyzer);
295}

References aliasAnalyzers_.

Referenced by DataDependenceGraphBuilder(), and DataDependenceGraphBuilder().

◆ analyzeMemoryAlias()

MemoryAliasAnalyzer::AliasingResult DataDependenceGraphBuilder::analyzeMemoryAlias ( const ProgramOperation pop1,
const ProgramOperation pop2,
MoveNodeUse::BBRelation  bbInfo 
)
protected

Gets the address-writing move of a move which is a trigger or operand to a memory operation.

If none found, return null

Parameters
mnmoveNode whose address write move is being searched.
Returns
MoveNode which writes address to a mem operation or NULL.

MoveNode* DataDependenceGraphBuilder::addressMove(const MoveNode& mn) { if (mn.isDestinationOperation()) { return addressOperandMove(mn.destinationOperation()); } return NULL; } Delegates the call to all registered memory address alias analyzers.

Returns the first non-unknown result. If no alias analyzer can analyze these, returns ALIAS_UNKNOWN

Returns
Whether the memory accesses in the given moves alias.

Definition at line 1951 of file DataDependenceGraphBuilder.cc.

1953 {
1954
1955 for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
1956 MemoryAliasAnalyzer* analyzer = aliasAnalyzers_[i];
1958 analyzer->analyze(*currentDDG_, pop1, pop2, bbInfo);
1960 return res;
1961 }
1962 }
1964}
virtual AliasingResult analyze(DataDependenceGraph &ddg, const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)=0

References MemoryAliasAnalyzer::ALIAS_UNKNOWN, aliasAnalyzers_, MemoryAliasAnalyzer::analyze(), and currentDDG_.

Referenced by checkAndCreateMemDep(), hasEarlierMemWriteToSameAddressWithSameGuard(), and updateMemAndFuAliveAfter().

Here is the call graph for this function:

◆ appendMoveNodeUse()

void DataDependenceGraphBuilder::appendMoveNodeUse ( const LiveRangeData::MoveNodeUseSet src,
LiveRangeData::MoveNodeUseSet dst,
bool  setLoopProperty 
)
protected

◆ appendUseMapSets()

bool DataDependenceGraphBuilder::appendUseMapSets ( const MoveNodeUseMapSet srcMap,
MoveNodeUseMapSet dstMap,
bool  addLoopProperty 
)
protected

◆ build() [1/2]

DataDependenceGraph * DataDependenceGraphBuilder::build ( ControlFlowGraph cfg,
DataDependenceGraph::AntidependenceLevel  antidependenceLevel,
const TTAMachine::Machine mach,
const UniversalMachine um = NULL,
bool  createMemAndFUDeps = true,
bool  createDeathInformation = true,
llvm::AliasAnalysis AA = NULL 
)
virtual

Builds a DDG from a CFG.

Parameters
cfgControl flow graph where the ddg is built from.
antidependenceLevellevel of register antidependencies to create.
umuniversalmachine used for the code if registers unallocated. if null, assumed that registers allready allocated.
createMemAndFUDepswhether to create also memory and fu state(side effect) dependencies or only register deps.
createDeathInformationwhether to search the last usage of all liveranges. This is needed for things like register renamer and threading.
Returns
pointer to the ddg which is created.

Definition at line 2120 of file DataDependenceGraphBuilder.cc.

2126 {
2127
2128 mach_ = &mach;
2129 if (AA) {
2130 for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
2131 LLVMAliasAnalyzer* llvmaa =
2132 dynamic_cast<LLVMAliasAnalyzer*>(aliasAnalyzers_[i]);
2133 if (llvmaa != NULL) {
2134 llvmaa->setLLVMAA(AA);
2135 }
2136 }
2137 }
2138
2139 cfg_ = &cfg;
2140
2141 // @TODO: when CFG subgraphs are in use, 2nd param not always true
2143 allParamRegs_, cfg.name(), antidependenceLevel, NULL, true,
2144 false);
2145 try {
2146 // this is just for old frontend code.
2147 if (um != NULL) {
2149 } else {
2151 }
2152
2153 currentDDG_ = ddg;
2154
2155 // do the first phase (register dependencies and operation edges)
2157
2158 // then do the second phase - mem and fu deps.
2159 if (createMemAndFUDeps) {
2161 }
2162
2163 // search when registers are used for last time.
2164 // this live range information is used by register renamer and
2165 // threading.
2166 if (createDeathInformation) {
2168 }
2169
2170 // clear bookkeeping which is not needed anymore.
2172 } catch (const Exception& e) {
2174 << e.fileName() << ": " << e.lineNum() << ": " << e.errorMessageStack()
2175 << std::endl;
2176 delete ddg;
2177 throw;
2178 } catch (...) {
2179 delete ddg;
2180 throw;
2181 }
2182 ddg->setMachine(mach);
2183 return ddg;
2184}
virtual const TCEString & name() const
void findStaticRegisters(TTAProgram::CodeSnippet &cs, std::map< int, TCEString > &registers)
find special register data from old frontend code
const TTAMachine::Machine * mach_
void setMachine(const TTAMachine::Machine &machine)
std::string errorMessageStack(bool messagesOnly=false) const
Definition Exception.cc:138
std::string fileName() const
int lineNum() const
virtual void setLLVMAA(llvm::AliasAnalysis *AA)

References aliasAnalyzers_, allParamRegs_, cfg_, clearUnneededBookkeeping(), createMemAndFUstateDeps(), createRegisterDeps(), currentDDG_, Exception::errorMessageStack(), Exception::fileName(), findStaticRegisters(), Exception::lineNum(), Application::logStream(), mach_, BoostGraph< GraphNode, GraphEdge >::name(), searchRegisterDeaths(), LLVMAliasAnalyzer::setLLVMAA(), DataDependenceGraph::setMachine(), and specialRegisters_.

Referenced by BUMoveNodeSelector::BUMoveNodeSelector(), llvm::LLVMTCEIRBuilder::compileOptimized(), BasicBlockPass::createDDGFromBB(), BBSchedulerController::createDDGFromBB(), CriticalPathBBMoveNodeSelector::CriticalPathBBMoveNodeSelector(), PreOptimizer::handleControlFlowGraph(), BBSchedulerController::handleProcedure(), and ProgramGraph::ProgramGraph().

Here is the call graph for this function:

◆ build() [2/2]

DataDependenceGraph * DataDependenceGraphBuilder::build ( TTAProgram::BasicBlock bb,
DataDependenceGraph::AntidependenceLevel  registerAntidependenceLevel,
const TTAMachine::Machine mach,
const TCEString ddgName = "small bb",
const UniversalMachine um = NULL,
bool  createMemAndFUDeps = true,
llvm::AliasAnalysis AA = NULL 
)
virtual

Creates new Data Dependence Graph for the given basic block.

Client has to delete the graph when it is not anymore used.

Parameters
bbBasicBlockNode whose data dependence graph to build.
registerAntidependenceLevelwhich reg antidependencies to create
createMemAndFUDepswhether to create also memory and fu state(side effect) dependencies or only register deps.
Returns
new DataDependence Graph.

Definition at line 456 of file DataDependenceGraphBuilder.cc.

463 {
464
465 mach_ = &mach;
466 if (AA) {
467 for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
468 LLVMAliasAnalyzer* llvmaa =
469 dynamic_cast<LLVMAliasAnalyzer*>(aliasAnalyzers_[i]);
470 if (llvmaa != NULL) {
471 llvmaa->setLLVMAA(AA);
472 }
473 }
474 }
475 if (bb.liveRangeData_ == NULL) {
477 }
478
479 currentBB_ = new BasicBlockNode(bb);
481 allParamRegs_, ddgName, registerAntidependenceLevel, currentBB_,
482 false,true);
483 // GRR, start and end addresses are lost..
484
485 currentData_ = new BBData(*currentBB_);
486
487 if (um != NULL) {
489 } else {
491 }
492 try {
493 // first phase. registers , ops and PO's.
496 if (createMemAndFUDeps) {
497 //second phase. mem and fu state deps
500 }
501 } catch (Exception&) {
502 delete currentDDG_; currentDDG_ = NULL;
503 delete currentData_; currentData_ = NULL;
504 delete currentBB_; currentBB_ = NULL;
505 throw;
506 }
507
508 clearUnneededBookkeeping(bb, false);
509
510 delete currentData_;
511 currentData_ = NULL;
512 currentDDG_->setMachine(mach);
513 return currentDDG_;
514}
void constructIndividualBB(ConstructionPhase phase)
LiveRangeData * liveRangeData_

References aliasAnalyzers_, allParamRegs_, clearUnneededBookkeeping(), constructIndividualBB(), currentBB_, currentData_, currentDDG_, findStaticRegisters(), TTAProgram::BasicBlock::liveRangeData_, mach_, MEMORY_AND_SIDE_EFFECTS, REGISTERS_AND_PROGRAM_OPERATIONS, LLVMAliasAnalyzer::setLLVMAA(), DataDependenceGraph::setMachine(), and specialRegisters_.

Here is the call graph for this function:

◆ changeState()

void DataDependenceGraphBuilder::changeState ( BBData bbd,
BBState  newState,
bool  priorize = false 
)
protected

Changes state of a basic block in processing. Move BBData into a diffefent list and changes the state data in BBData.

Parameters
bbdBBData of basic block whose state is being changed
newStatethe new state of the basic block.

Definition at line 2217 of file DataDependenceGraphBuilder.cc.

2218 {
2219
2220 BBState oldState = bbd.state_;
2221 if (newState != oldState) {
2223 bbd.state_ = newState;
2224 if (priorize) {
2225 blocksByState_[newState].push_front(&bbd);
2226 } else {
2227 blocksByState_[newState].push_back(&bbd);
2228 }
2229 }
2230}
static bool removeValueIfExists(ContainerType &aContainer, const ElementType &aKey)

References blocksByState_, ContainerTools::removeValueIfExists(), and DataDependenceGraphBuilder::BBData::state_.

Referenced by createMemAndFUstateDeps(), createRegisterDeps(), iterateBBs(), iterateRegisterDeaths(), queueFirstBB(), searchRegisterDeaths(), setSucceedingPredepsForBB(), and updatePreceedingRegistersUsedAfter().

Here is the call graph for this function:

◆ checkAndCreateMemAntideps()

void DataDependenceGraphBuilder::checkAndCreateMemAntideps ( MoveNodeUse mnd,
std::set< MoveNodeUse > &  prevNodes,
DataDependenceEdge::DependenceType  depType,
bool  traceable 
)
protected

Creates memory dependencies from set of nodes to given nodes.

Does not create if gaurds of aliasing dictate edge not needed. If both guard and aliasing indicate fully transitive case for some prev nodes, then remove these previous nodes from the bookkeeping.

Definition at line 1718 of file DataDependenceGraphBuilder.cc.

1721 {
1722 // create WaW to another in own bb
1723 for (MoveNodeUseSet::iterator iter =
1724 prevNodes.begin(); iter != prevNodes.end();) {
1725 if ((checkAndCreateMemDep(*iter, mnd, depType) || !traceable) &&
1726 (mnd.mn()->move().isUnconditional() ||
1727 currentDDG_->sameGuards(*(iter->mn()), *(mnd.mn())))) {
1728 // remove current element and update iterator to next.
1729 prevNodes.erase(iter++);
1730 } else { // just take next from the set
1731 iter++;
1732 }
1733 }
1734}
bool checkAndCreateMemDep(MoveNodeUse prev, MoveNodeUse mnd, DataDependenceEdge::DependenceType depType)
bool sameGuards(const MoveNode &mn1, const MoveNode &mn2) const
const MoveNode * mn() const
TTAProgram::Move & move()
bool isUnconditional() const
Definition Move.cc:154

References checkAndCreateMemDep(), currentDDG_, TTAProgram::Move::isUnconditional(), MoveNodeUse::mn(), MoveNode::move(), and DataDependenceGraph::sameGuards().

Referenced by processMemWrite().

Here is the call graph for this function:

◆ checkAndCreateMemDep()

bool DataDependenceGraphBuilder::checkAndCreateMemDep ( MoveNodeUse  prev,
MoveNodeUse  mnd,
DataDependenceEdge::DependenceType  depType 
)
protected

Compares a memory op against one previous memory ops and creates dependence if may alias.

Parameters
prevPrevious Memory write movenode
mnCurrent memory write movenode
depTypedependence type which to create.
Returns
true if true alias.

Definition at line 1841 of file DataDependenceGraphBuilder.cc.

1843 {
1844
1845 // cannot be dep if opposite guards.
1846 if (currentDDG_->exclusingGuards(*(prev.mn()), *(mnd.mn()))) {
1847 return false;
1848 }
1849
1852
1853 // only for true stores and loads; we cannot analyze aliasing
1854 // of pseudo dependencies caused by call/return.
1855 if (!prev.pseudo() && !mnd.pseudo()) {
1856 ProgramOperation& currPop = mnd.mn()->destinationOperation();
1857 ProgramOperation& prevPop = prev.mn()->destinationOperation();
1858
1859 const llvm::MachineInstr* instr1 = currPop.machineInstr();
1860 const llvm::MachineInstr* instr2 = prevPop.machineInstr();
1861
1862 // The LLVM MachineInstructions are not connected to
1863 // all memory operands, at least not to those in inline
1864 // assembly blocks (from custom operation calls).
1865 if (instr1 != NULL && instr2 != NULL) {
1866 llvm::MachineInstr::mmo_iterator begin1 =
1867 instr1->memoperands_begin();
1868 // Machine instruction could in theory have several memory operands.
1869 // In practice it is usually just one.
1870 while (begin1 != instr1->memoperands_end()) {
1871 llvm::MachineInstr::mmo_iterator begin2 =
1872 instr2->memoperands_begin();
1873
1874 while (begin2 != instr2->memoperands_end()) {
1875 // Force program ordering between volatile mem accesses.
1876 if ((*begin1)->isVolatile() && (*begin2)->isVolatile()) {
1877#if 0
1878 Application::logStream() << "MemDep >> volatile \n";
1879 PRINT_VAR(currPop.toString());
1880 PRINT_VAR(prevPop.toString());
1881 (*begin1)->getValue()->dump();
1882 (*begin2)->getValue()->dump();
1883#endif
1885 }
1886 begin2++;
1887 }
1888 begin1++;
1889 }
1890 }
1891 if (aliasResult == MemoryAliasAnalyzer::ALIAS_UNKNOWN)
1892 aliasResult = analyzeMemoryAlias(prevPop, currPop, prev.bbRelation());
1893 }
1894
1895 if (aliasResult != MemoryAliasAnalyzer::ALIAS_FALSE) {
1896 // if not alias false , have to create mem edge.
1897 bool trueAlias = (aliasResult == MemoryAliasAnalyzer::ALIAS_TRUE);
1898 ProgramOperation& prevPo = prev.mn()->destinationOperation();
1899 for (int i = 0; i < prevPo.inputMoveCount(); i++) {
1900 if (prev.loop() || &prevPo.inputMove(i) != mnd.mn()) {
1901 // if operations are always assigned to differnt FU,
1902 // then skip creating memroy dependency edge
1903 if (isAlwaysDifferentFU(prev.mn(), mnd.mn())) {
1904 continue;
1905 }
1906 DataDependenceEdge* dde2 =
1908 DataDependenceEdge::EDGE_MEMORY, depType, false,
1909 trueAlias, prev.pseudo(), mnd.pseudo(),
1910 static_cast<int>(prev.loop()));
1912 prevPo.inputMove(i), *mnd.mn(), dde2);
1913 }
1914 }
1915 return trueAlias;
1916 }
1917 return false;
1918}
#define PRINT_VAR(VARIABLE__)
MemoryAliasAnalyzer::AliasingResult analyzeMemoryAlias(const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)
bool isAlwaysDifferentFU(const MoveNode *srcMN, const MoveNode *dstMN)
bool exclusingGuards(const MoveNode &mn1, const MoveNode &mn2) const
bool connectOrDeleteEdge(const MoveNode &tailNode, const MoveNode &headNode, DataDependenceEdge *edge)
bool loop() const
BBRelation bbRelation() const
bool pseudo() const
ProgramOperation & destinationOperation(unsigned int index=0) const
const llvm::MachineInstr * machineInstr() const
int inputMoveCount() const
std::string toString() const
MoveNode & inputMove(int index) const

References MemoryAliasAnalyzer::ALIAS_FALSE, MemoryAliasAnalyzer::ALIAS_PARTIAL, MemoryAliasAnalyzer::ALIAS_TRUE, MemoryAliasAnalyzer::ALIAS_UNKNOWN, analyzeMemoryAlias(), MoveNodeUse::bbRelation(), DataDependenceGraph::connectOrDeleteEdge(), currentDDG_, MoveNode::destinationOperation(), DataDependenceEdge::EDGE_MEMORY, DataDependenceGraph::exclusingGuards(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), isAlwaysDifferentFU(), Application::logStream(), MoveNodeUse::loop(), ProgramOperation::machineInstr(), MoveNodeUse::mn(), PRINT_VAR, MoveNodeUse::pseudo(), and ProgramOperation::toString().

Referenced by checkAndCreateMemAntideps(), processMemUse(), updateMemUse(), and updateMemWrite().

Here is the call graph for this function:

◆ clearUnneededBookkeeping() [1/2]

void DataDependenceGraphBuilder::clearUnneededBookkeeping ( )
protected

Clears bookkeeping which is only needed during ddg construction.

Definition at line 2251 of file DataDependenceGraphBuilder.cc.

2251 {
2252
2253 for (int i = 0; i < cfg_->nodeCount();i++) {
2254 BasicBlockNode& bbn = cfg_->node(i);
2255 if (bbn.isNormalBB()) {
2256 BasicBlock& bb = bbn.basicBlock();
2257 clearUnneededBookkeeping(bb, true);
2258 }
2259 }
2260}
TTAProgram::BasicBlock & basicBlock()
bool isNormalBB() const
int nodeCount() const
Node & node(const int index) const

References BasicBlockNode::basicBlock(), cfg_, clearUnneededBookkeeping(), BasicBlockNode::isNormalBB(), BoostGraph< GraphNode, GraphEdge >::node(), and BoostGraph< GraphNode, GraphEdge >::nodeCount().

Referenced by build(), build(), and clearUnneededBookkeeping().

Here is the call graph for this function:

◆ clearUnneededBookkeeping() [2/2]

void DataDependenceGraphBuilder::clearUnneededBookkeeping ( TTAProgram::BasicBlock bb,
bool  interBBInformationNeeded = true 
)
protected

Clears bookkeeping which is only needed during ddg construction.

Parameters
BBcontaining basic blocks which contain the bookkeeping.
interBBInformationneeded whether information about inter-bb- dependencies need to be left intact.

Definition at line 899 of file DataDependenceGraphBuilder.cc.

900 {
901
902 if (!interBBInformationNeeded) {
903 //used by regcopyadder.
905 bb.liveRangeData_->regLastUses_.clear();
906
907 // used by both
908 bb.liveRangeData_->regDefines_.clear();
909
910 // these are neede for live range things
911 bb.liveRangeData_->regDefReaches_.clear();
913 bb.liveRangeData_->regFirstUses_.clear();
914 }
915 bb.liveRangeData_->regUseReaches_.clear();
916 bb.liveRangeData_->regLastKills_.clear();
917
918 bb.liveRangeData_->regDefAfter_.clear();
919 bb.liveRangeData_->regUseAfter_.clear();
920
921 bb.liveRangeData_->memDefines_.clear();
922 bb.liveRangeData_->memLastUses_.clear();
923
924 bb.liveRangeData_->memFirstUses_.clear();
926
927 bb.liveRangeData_->memDefReaches_.clear();
928 bb.liveRangeData_->memUseReaches_.clear();
929
930 bb.liveRangeData_->fuDepReaches_.clear();
931 bb.liveRangeData_->fuDeps_.clear();
932 bb.liveRangeData_->fuDepAfter_.clear();
933
935}
MoveNodeUseMapSet memFirstDefines_
MoveNodeUseMapSet memUseReaches_
MoveNodeUseMapSet regFirstUses_
MoveNodeUseMapSet regLastUses_
MoveNodeUseSet fuDepAfter_
MoveNodeUseMapSet memLastUses_
MoveNodeUseSet fuDepReaches_
MoveNodeUseMapSet regUseAfter_
MoveNodeUseMapSet regUseReaches_
std::set< TCEString > registersUsedAfter_
MoveNodeUseMapSet regFirstDefines_
MoveNodeUseMapSet memDefines_
MoveNodeUseMapSet regDefAfter_
std::set< TCEString > registersUsedInOrAfter_
MoveNodeUseSet fuDeps_
MoveNodeUseMapPair regLastKills_
MoveNodeUseMapSet regDefines_
MoveNodeUseMapSet memDefReaches_
MoveNodeUseMapSet memFirstUses_
MoveNodeUseMapSet regDefReaches_

References LiveRangeData::fuDepAfter_, LiveRangeData::fuDepReaches_, LiveRangeData::fuDeps_, TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefines_, LiveRangeData::memDefReaches_, LiveRangeData::memFirstDefines_, LiveRangeData::memFirstUses_, LiveRangeData::memLastUses_, LiveRangeData::memUseReaches_, LiveRangeData::regDefAfter_, LiveRangeData::regDefines_, LiveRangeData::regDefReaches_, LiveRangeData::regFirstDefines_, LiveRangeData::regFirstUses_, LiveRangeData::registersUsedAfter_, LiveRangeData::registersUsedInOrAfter_, LiveRangeData::regLastKills_, LiveRangeData::regLastUses_, LiveRangeData::regUseAfter_, and LiveRangeData::regUseReaches_.

◆ constructBB()

void DataDependenceGraphBuilder::constructBB ( BasicBlockNodeSet inputBlocks)
protected

◆ constructIndividualBB() [1/2]

void DataDependenceGraphBuilder::constructIndividualBB ( BBData bbd,
ConstructionPhase  phase 
)
protected

Constructs a Data Dependence Graph for a single basic block.

Goes thru all moves in the basic block and analyzes their dependencies, creates their ProgramOperations, MoveNodes and Edges, and adds the nodes and edges to the graph. Also used inside implementation of multi-BB-DDG-code. BB being analyzed has to be already set in member variable currentBB_, and the graph created and set into member variable currentBB_.

Parameters
bbdbasic block to constructs.
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 531 of file DataDependenceGraphBuilder.cc.

532 {
533
534 currentData_ = &bbd;
535 currentBB_ = bbd.bblock_;
536
537 // Parallel inline asm block are already marked as scheduled
538 // TODO: should BBN have isInlineAsm() method?
539 if (currentBB_->isScheduled()) {
541 } else {
543 }
544}
bool isScheduled() const
void constructIndividualFromInlineAsmBB(ConstructionPhase phase)

References DataDependenceGraphBuilder::BBData::bblock_, constructIndividualBB(), constructIndividualFromInlineAsmBB(), currentBB_, currentData_, and BasicBlockNode::isScheduled().

Here is the call graph for this function:

◆ constructIndividualBB() [2/2]

void DataDependenceGraphBuilder::constructIndividualBB ( ConstructionPhase  phase)
protected

Constructs a Data Dependence Graph for a single basic block.

Goes thru all moves in the basic block and analyzes their dependencies, creates their ProgramOperations, MoveNodes and Edges, and adds the nodes and edges to the graph. Also used inside implementation of multi-BB-DDG-code. BB being analyzed has to be already set in member variable currentBB_, and the graph created and set into member variable currentBB_.

Parameters
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 560 of file DataDependenceGraphBuilder.cc.

561 {
562
563 for (int ia = 0; ia < currentBB_->basicBlock().instructionCount(); ia++) {
565
566 for (int i = 0; i < ins.moveCount(); i++) {
567 auto movePtr = ins.movePtr(i);
568 Move& move = *movePtr;
569
570 MoveNode* moveNode = NULL;
571
572 // if phase is 0, create the movenode, and handle guard.
574 /* In case using the LLVMTCEIRBuilder, the POs have been built already
575 and set to corresponding TerminalFUPorts. Use those MoveNodes and
576 ProgramOperations instead of creating new ones here. NOTE: the
577 ownership of the MoveNodes is transferred to the DDG.
578 */
579 if (move.destination().isFUPort() &&
580 dynamic_cast<TerminalFUPort&>(move.destination()).
581 hasProgramOperation()) {
583 dynamic_cast<TerminalFUPort&>(move.destination()).
584 programOperation();
585 if (po->hasMoveNodeForMove(move)) {
586 moveNode = &po->moveNode(move);
587 } else {
588 // the po might be corrupted and point to an old POM's Moves
589 moveNode = new MoveNode(movePtr);
590 }
591 } else if (move.source().isFUPort() &&
592 dynamic_cast<TerminalFUPort&>(move.source()).
593 hasProgramOperation()) {
595 dynamic_cast<TerminalFUPort&>(move.source()).
596 programOperation();
597 if (po->hasMoveNodeForMove(move)) {
598 moveNode = &po->moveNode(move);
599 } else {
600 // the po might be corrupted and point to an old POM's Moves
601 moveNode = new MoveNode(movePtr);
602 }
603 } else {
604 moveNode = new MoveNode(movePtr);
605 }
606 currentDDG_->addNode(*moveNode, *currentBB_);
607
608 if (!move.isUnconditional()) {
609 processGuard(*moveNode);
610 }
611
612 processSource(*moveNode);
613
614 } else {
615 // on phase 2, just find the already created movenode.
616 moveNode = &currentDDG_->nodeOfMove(move);
617 }
618
619 // destinaition need to be processed in both phases 0 and 1.
620 processDestination(*moveNode, phase);
621 }
622 }
623
624 // these are needed no more.
626
627 // Checks if we have some unready program operations at the end
628 // of a basic block.
629 if (currentData_->destPending_ != NULL ||
630 currentData_->readPending_ != NULL) {
631
632 TCEString msg = TCEString("Basic block ")
634 + TCEString(" - ")
636 + TCEString(", size : ")
639 + TCEString(" handled but we have unready PO at: ")
640 + currentDDG_->name()
641 + TCEString(", probably an operation without result move?");
642
643 if (currentData_->readPending_ != NULL) {
644 msg += "\n\tmissing read: " +
645 TCEString(currentData_->readPending_->operation().name());
646 }
647
648 if (currentData_->destPending_ != NULL) {
649 msg += "\n\tmissing dest: " +
650 TCEString(currentData_->destPending_->operation().name());
651 }
652
653 if (cfg_ != NULL) {
654 cfg_->writeToDotFile("constructBBbroken_cfg.dot");
655 }
656
657 throw IllegalProgram(__FILE__,__LINE__,__func__, msg);
658 }
659}
#define __func__
std::shared_ptr< ProgramOperation > ProgramOperationPtr
Definition MoveNode.hh:53
InstructionAddress originalEndAddress() const
InstructionAddress originalStartAddress() const
void processDestination(class MoveNode &moveNode, ConstructionPhase phase)
void addNode(MoveNode &moveNode)
MoveNode & nodeOfMove(const TTAProgram::Move &move)
virtual void writeToDotFile(const TCEString &fileName) const
virtual int instructionCount() const
virtual Instruction & instructionAtIndex(int index) const
std::shared_ptr< Move > movePtr(int i) const
Terminal & source() const
Definition Move.cc:302
Terminal & destination() const
Definition Move.cc:323
virtual bool isFUPort() const
Definition Terminal.cc:118
ProgramOperationPtr readPending_
ProgramOperations lacking result read.
ProgramOperationPtr destPending_
ProgramOperations lacking operands.
std::map< TCEString, std::pair< MoveNodeUse, bool > > potentialRegKills_

References __func__, DataDependenceGraph::addNode(), BasicBlockNode::basicBlock(), cfg_, currentBB_, currentData_, currentDDG_, TTAProgram::Move::destination(), DataDependenceGraphBuilder::BBData::destPending_, TTAProgram::CodeSnippet::instructionAtIndex(), TTAProgram::CodeSnippet::instructionCount(), TTAProgram::Terminal::isFUPort(), TTAProgram::Move::isUnconditional(), TTAProgram::BasicBlock::liveRangeData_, TTAProgram::Instruction::moveCount(), TTAProgram::Instruction::movePtr(), BoostGraph< GraphNode, GraphEdge >::name(), DataDependenceGraph::nodeOfMove(), BasicBlockNode::originalEndAddress(), BasicBlockNode::originalStartAddress(), LiveRangeData::potentialRegKills_, processDestination(), processGuard(), processSource(), DataDependenceGraphBuilder::BBData::readPending_, REGISTERS_AND_PROGRAM_OPERATIONS, TTAProgram::Move::source(), Conversion::toString(), and GraphBase< GraphNode, GraphEdge >::writeToDotFile().

Referenced by build(), constructIndividualBB(), and iterateBBs().

Here is the call graph for this function:

◆ constructIndividualFromInlineAsmBB()

void DataDependenceGraphBuilder::constructIndividualFromInlineAsmBB ( ConstructionPhase  phase)
protected

Same as constructIndividualBB() but for already fully scheduled and inline asm BB.

@Note: currently, this does not really construct DDG - just creates dummy MoveNodes.

Definition at line 669 of file DataDependenceGraphBuilder.cc.

670 {
671
673 return;
674 }
675 auto& bb = currentBB_->basicBlock();
677 for (int ia = 0; ia < bb.instructionCount(); ia++) {
678 Instruction& ins = bb.instructionAtIndex(ia);
679 for (int i = 0; i < ins.moveCount(); i++) {
680 MoveNode* moveNode = new MoveNode(ins.movePtr(i));
681 currentDDG_->addNode(*moveNode, *currentBB_);
682 }
683 }
684
685 // Process live range with dummy move nodes.
686 assert(bb.liveRangeData_);
687 LiveRangeData& liveRangeData = *bb.liveRangeData_;
688 std::set<TCEString> actualRegUses;
689 std::set<TCEString> actualRegDefs;
690 for (int i = 0; i < bb.instructionCount(); i++) {
691 auto& ins = bb.instructionAtIndex(i);
692 for (int m = 0; m < ins.moveCount(); m++) {
693 auto& move = ins.move(m);
694
695 auto rdReg = move.source().isGPR() ? move.source().toString()
696 : TCEString("");
697 if (!rdReg.empty()) actualRegUses.insert(rdReg);
698
699 if (move.isConditional()) {
700 const Guard& grd = move.guard().guard();
701 const RegisterGuard* grdReg =
702 dynamic_cast<const RegisterGuard*>(&grd);
703 if (grdReg) {
704 TCEString regName = grdReg->registerFile()->name() + '.' +
706 actualRegUses.insert(regName);
707 }
708 }
709
710 auto wrReg = move.destination().isGPR()
711 ? move.destination().toString()
712 : TCEString("");
713 if (!wrReg.empty()) actualRegDefs.insert(wrReg);
714 }
715 }
716
717 auto& iaRegUses = liveRangeData.inlineAsmRegUses_;
718 auto effectiveRegUses = SetTools::intersection(iaRegUses, actualRegUses);
719 for (auto reg : effectiveRegUses) {
720 MoveNode* moveNode = new MoveNode();
721 currentDDG_->addNode(*moveNode, *currentBB_);
722 liveRangeData.regFirstUses_[reg].insert(*moveNode);
723 currentDDG_->updateRegUse(*moveNode, reg, bb);
724 }
725
726 auto& iaRegDefs = liveRangeData.inlineAsmRegDefs_;
727 auto effectiveRegDefs = SetTools::intersection(iaRegDefs, actualRegDefs);
728 for (auto reg : effectiveRegDefs) {
729 MoveNode* moveNode = new MoveNode();
730 currentDDG_->addNode(*moveNode, *currentBB_);
731 liveRangeData.regDefines_[reg].insert(*moveNode);
732 MoveNodeUse mnd(*moveNode);
733 liveRangeData.regKills_[reg] = std::make_pair(mnd, mnd);
734 }
735
736 for (auto& reg : liveRangeData.inlineAsmClobbers_) {
737 MoveNode* moveNode = new MoveNode();
738 currentDDG_->addNode(*moveNode, *currentBB_);
739 liveRangeData.regDefines_[reg].insert(*moveNode);
740 MoveNodeUse mnd(*moveNode);
741 liveRangeData.regKills_[reg] = std::make_pair(mnd, mnd);
742 }
743
744 // Not needed anymore.
745 liveRangeData.inlineAsmRegUses_.clear();
746 liveRangeData.inlineAsmRegDefs_.clear();
747 liveRangeData.inlineAsmClobbers_.clear();
748}
#define assert(condition)
void updateRegUse(const MoveNodeUse &mnd, const TCEString &reg, TTAProgram::BasicBlock &bb)
static void intersection(const std::set< ValueType > &firstContainer, const std::set< ValueType > &secondContainer, std::set< ValueType > &intersection)
virtual TCEString name() const
const RegisterFile * registerFile() const
Move & move(int i) const
virtual bool isGPR() const
Definition Terminal.cc:107
std::set< TCEString > inlineAsmClobbers_
MoveNodeUseMapPair regKills_
std::set< TCEString > inlineAsmRegDefs_
std::set< TCEString > inlineAsmRegUses_

References DataDependenceGraph::addNode(), assert, BasicBlockNode::basicBlock(), currentBB_, currentDDG_, LiveRangeData::inlineAsmClobbers_, LiveRangeData::inlineAsmRegDefs_, LiveRangeData::inlineAsmRegUses_, SetTools::intersection(), BasicBlockNode::isScheduled(), TTAProgram::Instruction::moveCount(), TTAProgram::Instruction::movePtr(), TTAMachine::Component::name(), LiveRangeData::regDefines_, LiveRangeData::regFirstUses_, TTAMachine::RegisterGuard::registerFile(), TTAMachine::RegisterGuard::registerIndex(), REGISTERS_AND_PROGRAM_OPERATIONS, LiveRangeData::regKills_, Conversion::toString(), and DataDependenceGraph::updateRegUse().

Referenced by constructIndividualBB().

Here is the call graph for this function:

◆ createMemAndFUstateDeps()

void DataDependenceGraphBuilder::createMemAndFUstateDeps ( )
protected

Does the second phase of ddg construction.

handles mem deps and fu state deps.

Definition at line 2312 of file DataDependenceGraphBuilder.cc.

2312 {
2313
2314 // initializes states of all BB's to unreached.
2316
2317 // queues first bb for processing
2318 queueFirstBB();
2319
2320 // then iterates over all basic blocks.
2322
2323 // all should be constructed, but if there are unreachable BB's
2324 // we might want to handle those also
2325 while (!blocksByState_[BB_UNREACHED].empty()) {
2328 }
2329 // free bb data
2331}
static void deleteAllValues(ContainerType &aMap)
void iterateBBs(ConstructionPhase phase)
void changeState(BBData &bbd, BBState newState, bool priorize=false)

References BB_QUEUED, BB_UNREACHED, bbData_, blocksByState_, changeState(), AssocTools::deleteAllValues(), initializeBBStates(), iterateBBs(), MEMORY_AND_SIDE_EFFECTS, and queueFirstBB().

Referenced by build().

Here is the call graph for this function:

◆ createOperationEdges()

void DataDependenceGraphBuilder::createOperationEdges ( ProgramOperationPtr  po)
protected

Creates operand edges between input and output moves of a programoperation.

Parameters
poProgramOperation whose egdes we are creating.

Definition at line 1141 of file DataDependenceGraphBuilder.cc.

1142 {
1143
1144 const Operation& op = po->operation();
1145
1146 // loop over all input nodes
1147 for (int i = 0; i < po->inputMoveCount(); i++) {
1148 MoveNode& inputNode = po->inputMove(i);
1149 // loop over all output nodes.
1150 for (int j = 0; j < po->outputMoveCount(); j++) {
1151 MoveNode& outputNode = po->outputMove(j);
1152
1153 // and create operation edges
1154 // from all input nodes to all
1155 // output nodes.
1156 DataDependenceEdge* dde =
1160 op.name());
1161
1163 inputNode, outputNode, dde);
1164 }
1165 }
1166}
virtual TCEString name() const
Definition Operation.cc:93

References DataDependenceGraph::connectOrDeleteEdge(), currentDDG_, DataDependenceEdge::DEP_UNKNOWN, DataDependenceEdge::EDGE_OPERATION, and Operation::name().

Referenced by LLVMTCEDataDependenceGraphBuilder::buildLocalDDG(), and processResultRead().

Here is the call graph for this function:

◆ createRegisterAntideps()

void DataDependenceGraphBuilder::createRegisterAntideps ( const TCEString reg,
MoveNodeUse mnd,
MoveNodeUseSet predecessorNodes,
DataDependenceEdge::DependenceType  depType,
bool  guardedKillFound 
)
protected

Creates register antidependencies from set of movenodeuses to one movenode.

Parameters
mndMovenode which to creat those dependencies
predecessorNodesNodes where to create dependencies from
depTypewhether to create WAR or WAW antidependencies
guardedKillFoundif there is a write with same guard to the reg.

Definition at line 1303 of file DataDependenceGraphBuilder.cc.

1307 {
1308
1309 // create dep to another in own bb
1310 for (std::set<MoveNodeUse>::iterator i = predecessorNodes.begin();
1311 i != predecessorNodes.end();) {
1312
1313 if (depType == DataDependenceEdge::DEP_WAW) {
1314 // If we do not have a guarded kill, draw edges from all defines.
1315 // If we have a guarded kill, only draw edges from
1316 // unconditional moves, as the guarded kill overshadows the
1317 // inconditional writes.
1318 if (guardedKillFound && i->mn()->move().isUnconditional()) {
1319 i++;
1320 continue;
1321 }
1322 } else {
1324 // skip if war to itself, ie move foo.1 -> foo.1
1325 if (i->mn() == mnd.mn()) {
1326 i++;
1327 continue;
1328 }
1329 }
1330
1331 // Do not create antideps if have excluding guards
1332 // But always create antidep if this writes to a reg which is
1333 // used as guard for the previous move.
1334 if (!currentDDG_->exclusingGuards(*(i->mn()), *(mnd.mn())) ||
1335 i->guard()) {
1336
1337 // create dependency edge
1338 DataDependenceEdge* dde =
1341 DataDependenceEdge::EDGE_REGISTER,
1342 depType, reg, i->guard(), false,
1343 i->pseudo(), mnd.pseudo(), i->loop());
1344
1345 // and connect
1346 currentDDG_->connectOrDeleteEdge(*i->mn(), *mnd.mn(), dde);
1347
1348 // if have same guards, remove the old from bookkeeping
1349 // this completely overshadows it
1350 if (currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1351 predecessorNodes.erase(i++);
1352 continue;
1353 }
1354 }
1355 i++;
1356 }
1357}
find Finds info of the inner loops in the false
bool ra() const

References assert, DataDependenceGraph::connectOrDeleteEdge(), currentDDG_, DataDependenceEdge::DEP_WAR, DataDependenceEdge::DEP_WAW, DataDependenceEdge::EDGE_RA, DataDependenceEdge::EDGE_REGISTER, DataDependenceGraph::exclusingGuards(), MoveNodeUse::mn(), MoveNodeUse::pseudo(), MoveNodeUse::ra(), and DataDependenceGraph::sameGuards().

Referenced by processRegWrite().

Here is the call graph for this function:

◆ createRegisterDeps()

void DataDependenceGraphBuilder::createRegisterDeps ( )
protected

Does the first phase of ddg construction. handles register deps.

Parameters
cfgcontrol flow graph containing the code.

Definition at line 2268 of file DataDependenceGraphBuilder.cc.

2268 {
2269
2270 // initializes states of all BB's to unreached.
2272
2273 // queues first bb for processing
2274 BasicBlockNode* firstBB = queueFirstBB();
2275
2276 // currentBB need to be set for entry node processing
2277 currentBB_ = firstBB;
2278
2279 // set entry deps. ( procedure parameter edges )
2280 MoveNode* entryNode = new MoveNode();
2281 currentDDG_->addNode(*entryNode, cfg_->entryNode());
2282
2283 processEntryNode(*entryNode);
2284
2285 // iterate over BB's. Loop as long as there are queued BB's.
2286
2288
2289 // all should be constructed, but if there are unreachable BB's
2290 // we handle those also
2291 while (!blocksByState_[BB_UNREACHED].empty()) {
2293 Application::logStream() << "Warning: Unreachable Basic Block!"
2294 << std::endl;
2295 Application::logStream() << "In procedure: " << cfg_->name() <<
2296 std::endl;
2297// cfg.writeToDotFile("unreachable_bb.dot");
2298 }
2301 }
2302 // free bb data
2304}
BasicBlockNode & entryNode() const

References DataDependenceGraph::addNode(), BB_QUEUED, BB_UNREACHED, bbData_, blocksByState_, cfg_, changeState(), currentBB_, currentDDG_, AssocTools::deleteAllValues(), ControlFlowGraph::entryNode(), initializeBBStates(), iterateBBs(), Application::logStream(), BoostGraph< GraphNode, GraphEdge >::name(), processEntryNode(), queueFirstBB(), REGISTERS_AND_PROGRAM_OPERATIONS, Application::VERBOSE_LEVEL_DEFAULT, and Application::verboseLevel().

Referenced by build().

Here is the call graph for this function:

◆ createSideEffectEdges()

void DataDependenceGraphBuilder::createSideEffectEdges ( MoveNodeUseSet prevMoves,
const MoveNode mn,
Operation dop 
)
protected

Definition at line 1646 of file DataDependenceGraphBuilder.cc.

1647 {
1648
1650 if (pool.sharesState(dop) || dop.hasSideEffects()) {
1651 for (MoveNodeUseSet::iterator i = prevMoves.begin();
1652 i != prevMoves.end(); i++) {
1653 const Operation& o = i->mn()->destinationOperation().operation();
1654
1655 // mem writes are handled by memory deps so exclude here
1656 if ((&dop == &o && o.hasSideEffects()) ||
1657 dop.dependsOn(o) || o.dependsOn(dop)) {
1658 // if operations are always assigned to differnt FU,
1659 // skip creating dependency edge
1660 if (isAlwaysDifferentFU(&mn, i->mn())) continue;
1661
1662 if (!currentDDG_->exclusingGuards(*(i->mn()), mn)) {
1663 DataDependenceEdge* dde =
1666 DataDependenceEdge::DEP_UNKNOWN, false,false,false,
1667 false, static_cast<int>(i->loop()));
1669 *(i->mn()), mn, dde);
1670 }
1671 }
1672 }
1673 }
1674}
virtual bool dependsOn(const Operation &op) const
Definition Operation.cc:458
virtual bool hasSideEffects() const
Definition Operation.cc:272
std::unique_ptr< OperationPool > pool

References DataDependenceGraph::connectOrDeleteEdge(), currentDDG_, DataDependenceEdge::DEP_UNKNOWN, Operation::dependsOn(), DataDependenceEdge::EDGE_FUSTATE, DataDependenceGraph::exclusingGuards(), Operation::hasSideEffects(), and isAlwaysDifferentFU().

Referenced by createTriggerDependencies(), and updateBB().

Here is the call graph for this function:

◆ createTriggerDependencies()

void DataDependenceGraphBuilder::createTriggerDependencies ( class MoveNode moveNode,
class Operation dop 
)
protected

Analyzes operation of a trigger write.

If memory read, calls processMemRead to manage memory read dependencies. Manages FU State dependencies between operations.

Parameters
moveNodemnData related to a move which triggers an operation
dopOperation being triggered

Definition at line 1596 of file DataDependenceGraphBuilder.cc.

1597 {
1598
1599 if (dop.readsMemory()) {
1600 processMemUse(MoveNodeUse(moveNode));
1601 } //TODO: avoid drawing antidep to itself
1602
1603 if (dop.writesMemory()) {
1604 processMemWrite(MoveNodeUse(moveNode));
1605 }
1606
1610
1612 if (dop.hasSideEffects() || pool.sharesState(dop)) {
1613
1614 // remove old same op from bookkeeping.
1615 // this should prevent exponential explosion of edge count.
1616 if (dop.hasSideEffects() && moveNode.move().isUnconditional()) {
1617 for (MoveNodeUseSet::iterator iter =
1619 iter != currentBB_->basicBlock().liveRangeData_->fuDeps_.end(); iter++) {
1620
1621 const Operation& o =
1622 iter->mn()->destinationOperation().operation();
1623 if (&o == &dop) {
1625 break;
1626 }
1627 }
1628 }
1629 // add the new one to bookkeeping
1631 }
1632}
void createSideEffectEdges(MoveNodeUseSet &prevMoves, const MoveNode &mn, Operation &dop)

References BasicBlockNode::basicBlock(), createSideEffectEdges(), currentBB_, LiveRangeData::fuDepReaches_, LiveRangeData::fuDeps_, Operation::hasSideEffects(), TTAProgram::Move::isUnconditional(), TTAProgram::BasicBlock::liveRangeData_, MoveNode::move(), processMemUse(), processMemWrite(), Operation::readsMemory(), and Operation::writesMemory().

Referenced by processTriggerMemoryAndFUStates().

Here is the call graph for this function:

◆ earlierWritesWithSameGuard()

std::set< MoveNodeUse > DataDependenceGraphBuilder::earlierWritesWithSameGuard ( MoveNodeUse mnd,
std::set< MoveNodeUse > &  defines 
)
protected

Definition at line 1200 of file DataDependenceGraphBuilder.cc.

1201 {
1202
1203 std::set<MoveNodeUse> results;
1204 // first just check if there is earlier write to this reg with same guard..
1205 for (std::set<MoveNodeUse>::iterator i = defines.begin();
1206 i != defines.end(); i++) {
1207 // if earlier write to this reg with same guard..
1208 if (!mnd.guard() &&
1209 !i->mn()->move().isUnconditional() &&
1210 currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1211 results.insert(*i);
1212 }
1213 }
1214 return results;
1215}
bool guard() const

References currentDDG_, MoveNodeUse::guard(), MoveNodeUse::mn(), and DataDependenceGraph::sameGuards().

Referenced by processRegUse().

Here is the call graph for this function:

◆ findStaticRegisters() [1/4]

void DataDependenceGraphBuilder::findStaticRegisters ( const UniversalMachine um,
std::map< int, TCEString > &  registers 
)
protected

Initializes the static register table from register from UniversalMachine.

Needed for analysis of data dependencies of parameter registers, SP, RV etc.

Parameters
umUniversalMachine
registersmap where to store those registers.

Definition at line 421 of file DataDependenceGraphBuilder.cc.

422 {
424
425 for (int i = 0; i < 6; i++) {
426 TerminalRegister tr(*rf.port(0), i);
428 registers[i] = reg;
429 if (i > REG_SP) {
430 allParamRegs_.insert(reg);
431 }
432 }
433}
static TCEString registerName(const TTAMachine::RegisterFile &rf, int index, char delim='.')
virtual RFPort * port(const std::string &name) const
UnboundedRegisterFile & integerRegisterFile() const

References allParamRegs_, UniversalMachine::integerRegisterFile(), TTAMachine::BaseRegisterFile::port(), REG_SP, and DisassemblyRegister::registerName().

Here is the call graph for this function:

◆ findStaticRegisters() [2/4]

void DataDependenceGraphBuilder::findStaticRegisters ( ControlFlowGraph cfg,
std::map< int, TCEString > &  registers 
)
protected

Tries to find annotations which tell the static registers from a program.

Used only with the old gcc frontend.

Parameters
cfgcfg where to search the annotations.

Definition at line 324 of file DataDependenceGraphBuilder.cc.

326 {
327 for (int i = 0; i < cfg.nodeCount(); i++) {
328 BasicBlockNode& bbn = cfg.node(i);
329 if (bbn.isNormalBB()) {
330 findStaticRegisters(bbn.basicBlock(), registers);
331 }
332 }
333}

References BasicBlockNode::basicBlock(), findStaticRegisters(), BasicBlockNode::isNormalBB(), BoostGraph< GraphNode, GraphEdge >::node(), and BoostGraph< GraphNode, GraphEdge >::nodeCount().

Here is the call graph for this function:

◆ findStaticRegisters() [3/4]

void DataDependenceGraphBuilder::findStaticRegisters ( TTAProgram::CodeSnippet cs,
std::map< int, TCEString > &  registers 
)
protected

find special register data from old frontend code

Tries to find annotations which tell the static registers from a program.

Used only with the old gcc frontend.

Parameters
cscodesnippet where to search the annotations.

Definition at line 306 of file DataDependenceGraphBuilder.cc.

308 {
309 for (int i = 0; i < cs.instructionCount(); i++) {
310 Instruction& ins = cs.instructionAtIndex(i);
311 findStaticRegisters(ins, registers);
312 }
313}

References findStaticRegisters(), TTAProgram::CodeSnippet::instructionAtIndex(), and TTAProgram::CodeSnippet::instructionCount().

Referenced by build(), build(), findStaticRegisters(), and findStaticRegisters().

Here is the call graph for this function:

◆ findStaticRegisters() [4/4]

void DataDependenceGraphBuilder::findStaticRegisters ( TTAProgram::Instruction ins,
std::map< int, TCEString > &  registers 
)
protected

Tries to find annotations which tell the static registers from a program.

Used only with the old gcc frontend.

Parameters
insinstruction where to search the annotations.

Definition at line 344 of file DataDependenceGraphBuilder.cc.

346 {
347
348 try {
349 for (int i = 0; i < ins.moveCount(); i++) {
350 Move& move = ins.move(i);
351 for (int j = 0; j < move.annotationCount(); j++) {
352 ProgramAnnotation anno = move.annotation(j);
353 switch (anno.id()) {
356 move.source());
357 break;
358 }
361 move.destination());
362 break;
363 }
366 move.source());
367 break;
368 }
371 move.destination());
372 break;
373 }
375/* this fixes one unit test silent breakage but another will then happen - unit test
376 tpef's seem to contain a bit broken code
377 Terminal& src = move.source();
378 if (!src.isGPR()) {
379 break;
380 }
381*/
382 TCEString reg =
384 registers[
386 reg;
387 allParamRegs_.insert(reg);
388 break;
389 }
391 TCEString reg =
393 registers[
395 reg;
396 allParamRegs_.insert(reg);
397 break;
398 }
399 default:
400 //TODO: frame pointer, not yet implemented
401 break;
402 }
403 }
404 }
405 } catch (std::bad_cast& e) {
406 throw IllegalProgram(__FILE__,__LINE__, __func__, "Illegal annotation");
407 }
408}
static int toInt(const T &source)
int annotationCount(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
ProgramAnnotation annotation(int index, ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
ProgramAnnotation::Id id() const
@ ANN_REGISTER_SP_READ
Stack Pointer read.
@ ANN_REGISTER_IPARAM_READ
Read from int param.
@ ANN_REGISTER_IPARAM_SAVE
Save to int param reg.
@ ANN_REGISTER_SP_SAVE
save to Stack pointer
@ ANN_REGISTER_RV_SAVE
Save to RV register.
@ ANN_REGISTER_RV_READ
Read from RV reg.

References __func__, allParamRegs_, TTAProgram::ProgramAnnotation::ANN_REGISTER_IPARAM_READ, TTAProgram::ProgramAnnotation::ANN_REGISTER_IPARAM_SAVE, TTAProgram::ProgramAnnotation::ANN_REGISTER_RV_READ, TTAProgram::ProgramAnnotation::ANN_REGISTER_RV_SAVE, TTAProgram::ProgramAnnotation::ANN_REGISTER_SP_READ, TTAProgram::ProgramAnnotation::ANN_REGISTER_SP_SAVE, TTAProgram::AnnotatedInstructionElement::annotation(), TTAProgram::AnnotatedInstructionElement::annotationCount(), TTAProgram::Move::destination(), TTAProgram::ProgramAnnotation::id(), TTAProgram::Instruction::move(), TTAProgram::Instruction::moveCount(), REG_IPARAM, REG_RV, REG_SP, DisassemblyRegister::registerName(), TTAProgram::Move::source(), TTAProgram::ProgramAnnotation::stringValue(), and Conversion::toInt().

Here is the call graph for this function:

◆ hasEarlierMemWriteToSameAddressWithSameGuard()

bool DataDependenceGraphBuilder::hasEarlierMemWriteToSameAddressWithSameGuard ( MoveNodeUse mnd,
std::set< MoveNodeUse > &  defines 
)
protected

Checks if there is an earlier write to same address or with same guard.

Parameters
mndthe current node dictating guard and mem address to check.
definesset of earlier writes to check for the write.

Definition at line 1688 of file DataDependenceGraphBuilder.cc.

1689 {
1690 // first just check if there is earlier write to this mem address
1691 // with same guard.
1692 for (std::set<MoveNodeUse>::iterator i = defines.begin();
1693 i != defines.end(); i++) {
1694 // if earlier write to this reg with same guard..
1695 if (currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1696 ProgramOperation& curPop = mnd.mn()->destinationOperation();
1697 ProgramOperation& prevPop = (i->mn())->destinationOperation();
1698// MoveNode* currentAddress = addressMove(*mnd.mn());
1699// MoveNode* prevAddress = addressMove(*(i->mn()));
1700 if (!isAddressTraceable(prevPop) ||
1701 analyzeMemoryAlias(prevPop, curPop, i->bbRelation()) ==
1703 return true;
1704 }
1705 }
1706 }
1707 return false;
1708}
bool isAddressTraceable(const ProgramOperation &pop)

References MemoryAliasAnalyzer::ALIAS_TRUE, analyzeMemoryAlias(), currentDDG_, MoveNode::destinationOperation(), isAddressTraceable(), MoveNodeUse::mn(), and DataDependenceGraph::sameGuards().

Referenced by processMemUse(), and processMemWrite().

Here is the call graph for this function:

◆ hasEarlierWriteWithSameGuard()

bool DataDependenceGraphBuilder::hasEarlierWriteWithSameGuard ( MoveNodeUse mnd,
std::set< MoveNodeUse > &  defines 
)
protected

Checks whether there is a previous alive write with same guard than given node.

The origin of the guard value is tracked from DDG, not only plain guard is done.

Parameters
mndMoveNode containing the guard.
definesset of earlier writes which to check.

Definition at line 1183 of file DataDependenceGraphBuilder.cc.

1184 {
1185
1186 // first just check if there is earlier write to this reg with same guard..
1187 for (std::set<MoveNodeUse>::iterator i = defines.begin();
1188 i != defines.end(); i++) {
1189 // if earlier write to this reg with same guard..
1190 if (!mnd.guard() &&
1191 !i->mn()->move().isUnconditional() &&
1192 currentDDG_->sameGuards(*(i->mn()), *(mnd.mn()))) {
1193 return true;
1194 }
1195 }
1196 return false;
1197}

References currentDDG_, MoveNodeUse::guard(), MoveNodeUse::mn(), and DataDependenceGraph::sameGuards().

Referenced by processRegWrite().

Here is the call graph for this function:

◆ initializeBBStates()

void DataDependenceGraphBuilder::initializeBBStates ( )
protected

Initializes states of all BB's to unreached

Definition at line 2191 of file DataDependenceGraphBuilder.cc.

2191 {
2192
2193 // initialize state lists
2194 for (int bbi = 0; bbi < cfg_->nodeCount(); bbi++) {
2195 BasicBlockNode& bbn = cfg_->node(bbi);
2196 BasicBlock& bb = bbn.basicBlock();
2197 if (bb.liveRangeData_ == NULL) {
2199 }
2200 BBData* bbd = new BBData(bbn);
2201 bbData_[&bbn] = bbd;
2202 // in the beginning all are unreached
2203 if (bbn.isNormalBB()) {
2204 blocksByState_[BB_UNREACHED].push_back(bbd);
2205 }
2206 }
2207}

References BasicBlockNode::basicBlock(), BB_UNREACHED, bbData_, blocksByState_, cfg_, BasicBlockNode::isNormalBB(), TTAProgram::BasicBlock::liveRangeData_, BoostGraph< GraphNode, GraphEdge >::node(), and BoostGraph< GraphNode, GraphEdge >::nodeCount().

Referenced by createMemAndFUstateDeps(), createRegisterDeps(), and searchRegisterDeaths().

Here is the call graph for this function:

◆ isAddressTraceable()

bool DataDependenceGraphBuilder::isAddressTraceable ( const ProgramOperation pop)
protected

Can some analyzer say something about this address?

Parameters
mnMovenode containing memory address write.
Returns
true if some alias analyzer knows something about the address, ie can return something else than ALIAS_UNKNOWN.

Definition at line 1974 of file DataDependenceGraphBuilder.cc.

1974 {
1975
1976 for (unsigned int i = 0; i < aliasAnalyzers_.size(); i++) {
1977 if (aliasAnalyzers_.at(i)->isAddressTraceable(*currentDDG_, pop)) {
1978 return true;
1979 }
1980 }
1981 return false;
1982}

References aliasAnalyzers_, and currentDDG_.

Referenced by hasEarlierMemWriteToSameAddressWithSameGuard(), and processMemWrite().

◆ isAlwaysDifferentFU()

bool DataDependenceGraphBuilder::isAlwaysDifferentFU ( const MoveNode srcMN,
const MoveNode dstMN 
)
protected

Check if operations are assigned to differnt FU

Operations forced to different FUs are independent since the operation state is per FU. Check if the moves have forced set of FUs and if the sets overlap.

Parameters
srcMNMoveNode first node for dependency check
dstMNMoveNode for which dependency needs to be checked
Returns
Nodes are alawys mapped to different FU

Definition at line 2994 of file DataDependenceGraphBuilder.cc.

2995 {
2996 if (srcMN->move().hasAnnotations(
2998 dstMN->move().hasAnnotations(
3000 bool alwaysDifferentFUs = true;
3001 for (int idx = 0;
3002 idx < srcMN->move().annotationCount(
3004 ++idx) {
3005 if (dstMN->move().hasAnnotation(
3007 srcMN->move()
3008 .annotation(
3010 ANN_ALLOWED_UNIT_DST)
3011 .stringValue())) {
3012 alwaysDifferentFUs = false;
3013 break;
3014 }
3015 }
3016 return alwaysDifferentFUs;
3017 }
3018 return false;
3019}
bool hasAnnotation(ProgramAnnotation::Id id, const TCEString &data) const
bool hasAnnotations(ProgramAnnotation::Id id=ProgramAnnotation::ANN_UNDEF_ID) const
@ ANN_ALLOWED_UNIT_DST
Dst. unit candidate.

References TTAProgram::ProgramAnnotation::ANN_ALLOWED_UNIT_DST, TTAProgram::AnnotatedInstructionElement::annotation(), TTAProgram::AnnotatedInstructionElement::hasAnnotation(), TTAProgram::AnnotatedInstructionElement::hasAnnotations(), and MoveNode::move().

Referenced by checkAndCreateMemDep(), and createSideEffectEdges().

Here is the call graph for this function:

◆ isTriggering()

bool DataDependenceGraphBuilder::isTriggering ( const MoveNode mn)
protected

Definition at line 810 of file DataDependenceGraphBuilder.cc.

810 {
811 int destIndex = mn.move().destination().operationIndex();
812 const Operation& op = mn.destinationOperation().operation();
813 int triggerIndex = MachineInfo::triggerIndex(*mach_, op);
814 switch (triggerIndex) {
815 case -1: {
816 TCEString msg = "Trigger index ambiguous for operation: ";
817 msg << op.name() << " in the machine.";
818 throw IllegalMachine(__FILE__,__LINE__,__func__, msg);
819 break;
820 }
821 case 0: {
822 TCEString msg = "Operation: ";
823 msg << op.name() << " Not found from the machine";
824 throw CompileError(__FILE__,__LINE__,__func__, msg);
825 break;
826 }
827 default:
828 return triggerIndex == destIndex;
829 }
830}
static int triggerIndex(const TTAMachine::Machine &machine, const Operation &op)
const Operation & operation() const
virtual int operationIndex() const
Definition Terminal.cc:364

References __func__, TTAProgram::Move::destination(), MoveNode::destinationOperation(), mach_, MoveNode::move(), Operation::name(), ProgramOperation::operation(), TTAProgram::Terminal::operationIndex(), and MachineInfo::triggerIndex().

Referenced by processDestination().

Here is the call graph for this function:

◆ iterateBBs()

void DataDependenceGraphBuilder::iterateBBs ( ConstructionPhase  phase)
protected

Iterates over basic blocks as long as there is some BB to process.

Handles a BB, updates the live value lists of its successors. If incoming live values of a BB change, it's scheduled for reprocessing.

Parameters
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 2345 of file DataDependenceGraphBuilder.cc.

2346 {
2347
2348 while (!blocksByState_[BB_QUEUED].empty()) {
2349 std::list<BBData*>::iterator bbIter =
2350 blocksByState_[BB_QUEUED].begin();
2351 BBData& bbd = **bbIter;
2352
2353 // construct or update BB
2354 if (bbd.constructed_) {
2355 updateBB(bbd, phase);
2356 } else {
2357 constructIndividualBB(bbd, phase);
2358 }
2359 // mark as ready
2360 changeState(bbd, BB_READY);
2361
2362 // create deps after and update that to succeeding BBs.
2363 // succeeding BB's are also queued to be scheduled here.
2364 // queue succeeding BB's in case either
2365 // * their input data has changed
2366 // * current BB was processed for the first time
2367 if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2368 if (updateRegistersAliveAfter(bbd) || !bbd.constructed_) {
2369 setSucceedingPredeps(bbd, !bbd.constructed_, phase);
2370 }
2371 } else {
2372 if (updateMemAndFuAliveAfter(bbd) || !bbd.constructed_) {
2373 setSucceedingPredeps(bbd, !bbd.constructed_, phase);
2374 }
2375 }
2376
2377 bbd.constructed_ = true;
2378 }
2379}
void updateBB(BBData &bbd, ConstructionPhase phase)
void setSucceedingPredeps(BBData &bbd, bool queueAll, ConstructionPhase phase)

References BB_QUEUED, BB_READY, blocksByState_, changeState(), DataDependenceGraphBuilder::BBData::constructed_, constructIndividualBB(), REGISTERS_AND_PROGRAM_OPERATIONS, setSucceedingPredeps(), updateBB(), updateMemAndFuAliveAfter(), and updateRegistersAliveAfter().

Referenced by createMemAndFUstateDeps(), and createRegisterDeps().

Here is the call graph for this function:

◆ iterateRegisterDeaths()

void DataDependenceGraphBuilder::iterateRegisterDeaths ( )
protected

Iterates thru all queued BB's and find register deaths from them.

Loops as long as something keeps changing.

Definition at line 2924 of file DataDependenceGraphBuilder.cc.

2924 {
2925
2926 // loop as long as we have unprocessed/changed BB's
2927 while (!blocksByState_[BB_QUEUED].empty()) {
2928 std::list<BBData*>::iterator bbIter =
2929 blocksByState_[BB_QUEUED].begin();
2930 BBData& bbd = **bbIter;
2931
2932 // mark as ready
2933 changeState(bbd, BB_READY);
2934
2935 if (updateRegistersUsedInOrAfter(bbd) || (!bbd.constructed_)) {
2936 // if there asre more registers read after start of this BB,
2937 // have to update this information to preceedign BBs,
2938 // and check if they need to be reprocessed.
2939 updatePreceedingRegistersUsedAfter(bbd, !bbd.constructed_);
2940 }
2941 bbd.constructed_ = true;
2942 }
2943}
void updatePreceedingRegistersUsedAfter(BBData &bbd, bool firstTime)

References BB_QUEUED, BB_READY, blocksByState_, changeState(), DataDependenceGraphBuilder::BBData::constructed_, updatePreceedingRegistersUsedAfter(), and updateRegistersUsedInOrAfter().

Referenced by searchRegisterDeaths().

Here is the call graph for this function:

◆ memoryCategory()

TCEString DataDependenceGraphBuilder::memoryCategory ( const MoveNodeUse mnd)
protected

Checks into which category this memory address belongs.

Memory accesses in different categories cannot alias, and there is separate bookkeeping for every category. Current implementation separates spills, different alias spaces, restrict keywords and opencl work items.

Parameters
mndMoveNodeUse which transfers the address of the memory operation.
Returns
string which is then used as key for map. unique for different categories, empty for the default category.

@TODO: create some memorycategorizer interface for this analysis?

Definition at line 1999 of file DataDependenceGraphBuilder.cc.

1999 {
2000
2001 TCEString category;
2002
2003// MoveNode* addressNode = addressMove(*mnd.mn());
2004// if (addressNode != NULL && addressNode->isMove()) {
2005 const TTAProgram::Move& move = mnd.mn()->move();//addressNode->move();
2006
2007 // spill annotations are in all operands.
2008 for (int j = 0; j < move.annotationCount(); j++) {
2010 if (anno.id() ==
2012 return "_SPILL";
2013 }
2014 if (anno.id() ==
2016 return "_RA";
2017 }
2018 if (anno.id() ==
2020 return "_FP";
2021 }
2022 if (anno.id() ==
2024 return "_CONSTANT";
2025 }
2026 }
2027 if (!mnd.mn()->isDestinationOperation()) {
2028 PRINT_VAR(mnd.mn()->toString());
2029 abortWithError("Not destination operation!");
2030 }
2032
2033 LLVMTCECmdLineOptions* llvmOptions =
2034 dynamic_cast<LLVMTCECmdLineOptions*>(
2036 if (llvmOptions == NULL || !llvmOptions->disableAddressSpaceAA()) {
2037 // address space
2038 for (int i = 0; i < po.inputMoveCount(); i++) {
2039 MoveNode& mn = po.inputMove(i);
2040 Move& m = mn.move();
2041 if (m.hasAnnotations(
2043 if (m.annotation(
2045 != "0") {
2046 category +=
2047 "_AS:" +
2048 m.annotation(
2050 .stringValue();
2051 break;
2052 }
2053 }
2054 }
2055 }
2056 for (int i = 0; i < po.inputMoveCount(); i++) {
2057 MoveNode& mn = po.inputMove(i);
2058 Move& m = mn.move();
2059 TCEString pointerName = "";
2060 // restrict keyword.
2061 if (m.hasAnnotations(
2065 pointerName =
2066 m.annotation(
2068 category += "_RESTRICT:" + pointerName;
2069 break;
2070 }
2071 }
2072
2073 /* OpenCL work item variable access.
2074
2075 OpenCL kernels enforce memory consistency for local and global
2076 memory only at explicit barrier() calls within a work group.
2077 Thus, all memory accesses between work items can be considered
2078 independent in alias analysis in the regions between barrier
2079 calls.
2080 */
2081 for (int i = 0; i < po.inputMoveCount(); i++) {
2082 MoveNode& mn = po.inputMove(i);
2083 Move& m = mn.move();
2085 category +=
2086 "_OPENCL_WI:" +
2088 m.annotation(
2090 intValue(), 8);
2091 break;
2092 }
2093 }
2094 return category;
2095}
#define abortWithError(message)
static std::string toHexString(T source, std::size_t digits=0, bool include0x=true)
bool isDestinationOperation() const
std::string toString() const
Definition MoveNode.cc:576
@ ANN_POINTER_NAME
information retrieved (from LLVM) about a pointer access
@ ANN_STACKUSE_FP_SAVE
frame ptr save/load
@ ANN_CONSTANT_MEM
Constant memory access.

References abortWithError, TTAProgram::ProgramAnnotation::ANN_CONSTANT_MEM, TTAProgram::ProgramAnnotation::ANN_OPENCL_WORK_ITEM_ID, TTAProgram::ProgramAnnotation::ANN_POINTER_ADDR_SPACE, TTAProgram::ProgramAnnotation::ANN_POINTER_NAME, TTAProgram::ProgramAnnotation::ANN_POINTER_NOALIAS, TTAProgram::ProgramAnnotation::ANN_STACKUSE_FP_SAVE, TTAProgram::ProgramAnnotation::ANN_STACKUSE_RA_SAVE, TTAProgram::ProgramAnnotation::ANN_STACKUSE_SPILL, TTAProgram::AnnotatedInstructionElement::annotation(), TTAProgram::AnnotatedInstructionElement::annotationCount(), Application::cmdLineOptions(), MoveNode::destinationOperation(), LLVMTCECmdLineOptions::disableAddressSpaceAA(), TTAProgram::AnnotatedInstructionElement::hasAnnotations(), TTAProgram::ProgramAnnotation::id(), ProgramOperation::inputMove(), ProgramOperation::inputMoveCount(), MoveNode::isDestinationOperation(), MoveNodeUse::mn(), MoveNode::move(), PRINT_VAR, TTAProgram::ProgramAnnotation::stringValue(), Conversion::toHexString(), and MoveNode::toString().

Referenced by processMemUse(), and processMemWrite().

Here is the call graph for this function:

◆ processCall()

void DataDependenceGraphBuilder::processCall ( MoveNode mn)
protected

Processes a call of a function.

Pseudo-reads from parameter registers and SP, writes to RV and RA.

Parameters
mnMoveNode containg the function call move.

Definition at line 1532 of file DataDependenceGraphBuilder.cc.

1532 {
1533
1534 // calls mess up RA. But immediately, not after delay slots?
1536 MoveNodeUse(mn, false, true, false), RA_NAME);
1537
1538 // MoveNodeUse for sp and rv(not guard, not ra, is pseudo)
1539 MoveNodeUse mnd2(mn, false,false, true);
1540
1541 // call is considered read of sp
1543 if (sp != "") {
1544 processRegUse(mnd2,sp);
1545 }
1546
1547 // call is considered as write of RV
1549 if (rv != "") {
1550 if (rvIsParamReg_) {
1551 processRegUse(mnd2,rv);
1552 }
1553 processRegWrite(mnd2,rv);
1554 }
1555
1556 // process all vector rv values
1557 for (int i = REG_VRV;;i--) {
1558 auto vrvIt = specialRegisters_.find(i);
1559 if (vrvIt != specialRegisters_.end()) {
1560 processRegWrite(mnd2, vrvIt->second);
1561 } else {
1562 break;
1563 }
1564 }
1565
1566 // call is considered as write of RV high (64-bit return values)
1568 if (rvh != "") {
1569 processRegWrite(mnd2, rvh);
1570 }
1571
1572 // params
1573 for (int i = 0; i < 4;i++) {
1575 if (paramReg != "") {
1576 processRegUse(mnd2, paramReg);
1577 }
1578 }
1579}
void processRegUse(MoveNodeUse mn, const TCEString &reg)
void processRegWrite(MoveNodeUse mn, const TCEString &reg)

References processRegUse(), processRegWrite(), RA_NAME, REG_IPARAM, REG_RV, REG_RV_HIGH, REG_SP, REG_VRV, rvIsParamReg_, and specialRegisters_.

Referenced by processTriggerRegistersAndOperations().

Here is the call graph for this function:

◆ processDestination()

void DataDependenceGraphBuilder::processDestination ( class MoveNode moveNode,
ConstructionPhase  phase 
)
protected

Analyzes destination of a move. Updates bookkeeping and handles WaW and WaR dependencies of the move.

Checks whether destination is operation or register and calls other functions to do the actual dependence checks etc.

Parameters
moveNodeMoveNode whose destination is being processed.
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 844 of file DataDependenceGraphBuilder.cc.

845 {
846 Terminal& dest = moveNode.move().destination();
847
848 // is this a operand to an operation?
849 if (dest.isFUPort()) {
850 if (!(dynamic_cast<const SpecialRegisterPort*>(&dest.port()))) {
851 TerminalFUPort& tfpd = dynamic_cast<TerminalFUPort&>(dest);
852 Operation &dop = tfpd.hintOperation();
853
855 if (tfpd.isOpcodeSetting()) {
857 moveNode, dop);
858 } else {
859 processOperand(moveNode, dop);
860 }
861 } else { // memory and fu state deps
862 if (dop.usesMemory() || dop.hasSideEffects() ||
863 dop.affectsCount() || dop.affectedByCount() ||
864 moveNode.move().isControlFlowMove()) {
865 if (isTriggering(moveNode)) {
866 processTriggerMemoryAndFUStates(moveNode, dop);
867 }
868 }
869 }
870 } else { // RA write
872 processRegWrite(MoveNodeUse(moveNode,false,true), RA_NAME);
873 }
874 }
875 } else {
876 if (dest.isGPR()) {
877 // we do not care about register reads in second phase
879 TerminalRegister& tr = dynamic_cast<TerminalRegister&>(dest);
881 processRegWrite(MoveNodeUse(moveNode), regName);
882 }
883 } else { // something else
884 throw IllegalProgram(__FILE__,__LINE__,__func__,
885 "Move has illegal destination" +
886 moveNode.toString());
887 }
888 }
889}
void processOperand(class MoveNode &moveNode, Operation &dop)
void processTriggerMemoryAndFUStates(MoveNode &moveNode, Operation &dop)
void processTriggerRegistersAndOperations(MoveNode &moveNode, Operation &dop)
virtual int affectedByCount() const
Definition Operation.cc:416
virtual bool usesMemory() const
Definition Operation.cc:232
virtual int affectsCount() const
Definition Operation.cc:402
virtual Operation & hintOperation() const
virtual bool isOpcodeSetting() const
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378

References __func__, Operation::affectedByCount(), Operation::affectsCount(), TTAProgram::Move::destination(), Operation::hasSideEffects(), TTAProgram::TerminalFUPort::hintOperation(), TTAProgram::Move::isControlFlowMove(), TTAProgram::Terminal::isFUPort(), TTAProgram::Terminal::isGPR(), TTAProgram::TerminalFUPort::isOpcodeSetting(), isTriggering(), MoveNode::move(), TTAProgram::Terminal::port(), processOperand(), processRegWrite(), processTriggerMemoryAndFUStates(), processTriggerRegistersAndOperations(), RA_NAME, DisassemblyRegister::registerName(), REGISTERS_AND_PROGRAM_OPERATIONS, MoveNode::toString(), and Operation::usesMemory().

Referenced by constructIndividualBB().

Here is the call graph for this function:

◆ processEntryNode()

void DataDependenceGraphBuilder::processEntryNode ( MoveNode mn)
protected

Processes the pseudo deps from entry node.

This procedure must be called when currentBB is the first real BB of the procedure.

Definition at line 2694 of file DataDependenceGraphBuilder.cc.

2694 {
2695
2696 // initializes RA
2698
2699 // sp
2700 MoveNodeUse mnd2(mn);
2702 if (sp != "") {
2704 }
2705
2706 if (rvIsParamReg_) {
2708 if (rv != "") {
2710 mnd2);
2711 }
2712 }
2713
2714 // params
2715 // this is for old frontend generated code.
2716 for (int i = 0;;i++) {
2718 if(paramReg != "") {
2719 currentBB_->basicBlock().liveRangeData_->regDefReaches_[paramReg].insert(mnd2);
2720 } else {
2721 break;
2722 }
2723 }
2724
2726 if (fp != "") {
2728 mnd2);
2729 }
2730}

References BasicBlockNode::basicBlock(), currentBB_, TTAProgram::BasicBlock::liveRangeData_, RA_NAME, REG_FP, REG_IPARAM, REG_RV, REG_SP, LiveRangeData::regDefReaches_, rvIsParamReg_, and specialRegisters_.

Referenced by createRegisterDeps().

Here is the call graph for this function:

◆ processGuard()

void DataDependenceGraphBuilder::processGuard ( MoveNode moveNode)
protected

Analyzes dependencies related to guard usage.

Finds the guard register used for the guard and the move Which writes the guard register, and creates a guard egde between them.

Parameters
moveNodeMNData of move containing guarded move.

Definition at line 760 of file DataDependenceGraphBuilder.cc.

760 {
761
762 // new code
763 const Guard& g = moveNode.move().guard().guard();
764 const RegisterGuard* rg = dynamic_cast<const RegisterGuard*>(&g);
765 if (rg != NULL) {
766 TCEString regName = rg->registerFile()->name() + '.' +
768 processRegUse(MoveNodeUse(moveNode, true),regName);
769 } else {
770 throw IllegalProgram(
771 __FILE__,__LINE__,__func__,
772 "Analysis for port guards not supported! used in: "
773 + moveNode.toString());
774 }
775}
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345

References __func__, TTAProgram::Move::guard(), TTAProgram::MoveGuard::guard(), MoveNode::move(), TTAMachine::Component::name(), processRegUse(), TTAMachine::RegisterGuard::registerFile(), TTAMachine::RegisterGuard::registerIndex(), MoveNode::toString(), and Conversion::toString().

Referenced by constructIndividualBB().

Here is the call graph for this function:

◆ processMemUse()

void DataDependenceGraphBuilder::processMemUse ( MoveNodeUse  mnd)
protected

Processes a memory read.

Creates dependence edges and updates bookkeeping.

Parameters
mndMoveNodeUse of MoveNode being processed.

Definition at line 1800 of file DataDependenceGraphBuilder.cc.

1800 {
1801
1802 TCEString category = memoryCategory(mnd);
1803
1804 // can be multiple if some write predicated
1805 std::set<MoveNodeUse>& defines =
1807
1808 // no kills/barriers to this one in this basic block.
1809 if (currentBB_->basicBlock().liveRangeData_->memKills_[category].mn() == NULL) {
1810
1811 // check if there is "guarded kill" to this mem address
1812 bool guardedKillFound =
1814
1815 if (!guardedKillFound) {
1816 currentBB_->basicBlock().liveRangeData_->memFirstUses_[category].insert(mnd);
1817 // so create deps from previous BB's
1818 updateMemUse(mnd, category);
1819 }
1820 }
1821
1822 // create deps from writes in this BB.LIVERANGEDATA_->
1823 for (MoveNodeUseSet::iterator iter =
1824 defines.begin(); iter != defines.end(); iter++) {
1826 }
1827 // update bookkeeping.
1828 currentBB_->basicBlock().liveRangeData_->memLastUses_[category].insert(mnd);
1829}
bool hasEarlierMemWriteToSameAddressWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
void updateMemUse(MoveNodeUse mnd, const TCEString &category)
TCEString memoryCategory(const MoveNodeUse &mnd)
MoveNodeUseMap memKills_

References BasicBlockNode::basicBlock(), checkAndCreateMemDep(), currentBB_, DataDependenceEdge::DEP_RAW, hasEarlierMemWriteToSameAddressWithSameGuard(), TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefines_, LiveRangeData::memFirstUses_, LiveRangeData::memKills_, LiveRangeData::memLastUses_, memoryCategory(), and updateMemUse().

Referenced by createTriggerDependencies().

Here is the call graph for this function:

◆ processMemWrite()

void DataDependenceGraphBuilder::processMemWrite ( MoveNodeUse  mnd)
protected

Updates memory operation bookkeeping and creates WaR and WaW memory dependencies.

Parameters
moveNodeMoveNodeUse related to Move whose memory write to are processing.

Definition at line 1744 of file DataDependenceGraphBuilder.cc.

1744 {
1745
1746 TCEString category = memoryCategory(mnd);
1747
1748 std::set<MoveNodeUse>& defines =
1750
1751 std::set<MoveNodeUse>& lastUses =
1753
1754 // check if no earlier barriers/kills to this one in this bb?
1755 if (currentBB_->basicBlock().liveRangeData_->memKills_[category].mn() == NULL) {
1756
1757 // is this a kill?
1758 if (mnd.mn()->move().isUnconditional() &&
1760 currentBB_->basicBlock().liveRangeData_->memKills_[category] = mnd;
1761 }
1762
1763 // check if there is "guarded kill" to this mem address
1764 bool guardedKillFound =
1766
1767 if (!guardedKillFound) {
1768 // may have incoming WaW's / WaRs to this
1769 currentBB_->basicBlock().liveRangeData_->memFirstDefines_[category].insert(mnd);
1770 updateMemWrite(mnd, category);
1771 }
1772 }
1773
1774 bool traceable = isAddressTraceable(mnd.mn()->destinationOperation());
1775
1777 mnd, defines, DataDependenceEdge::DEP_WAW, traceable);
1778
1780 mnd, lastUses, DataDependenceEdge::DEP_WAR, traceable);
1781
1782 // does this kill previous deps?
1783 if (mnd.mn()->move().isUnconditional() && !traceable) {
1785 defines.clear();
1786 lastUses.clear();
1787 }
1788
1789 defines.insert(mnd);
1790}
void checkAndCreateMemAntideps(MoveNodeUse &mnd, std::set< MoveNodeUse > &prevNodes, DataDependenceEdge::DependenceType depType, bool traceable)
void updateMemWrite(MoveNodeUse mnd, const TCEString &category)
MoveNodeUseMap memLastKill_

References BasicBlockNode::basicBlock(), checkAndCreateMemAntideps(), currentBB_, DataDependenceEdge::DEP_WAR, DataDependenceEdge::DEP_WAW, MoveNode::destinationOperation(), hasEarlierMemWriteToSameAddressWithSameGuard(), isAddressTraceable(), TTAProgram::Move::isUnconditional(), TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefines_, LiveRangeData::memFirstDefines_, LiveRangeData::memKills_, LiveRangeData::memLastKill_, LiveRangeData::memLastUses_, memoryCategory(), MoveNodeUse::mn(), MoveNode::move(), and updateMemWrite().

Referenced by createTriggerDependencies(), and processTriggerMemoryAndFUStates().

Here is the call graph for this function:

◆ processOperand()

void DataDependenceGraphBuilder::processOperand ( class MoveNode moveNode,
Operation dop 
)
protected

Analyzes operand writes.

Part of ProgramOperation creation.

Parameters
moveNodemnData related to a move which writes a parameter.
dopOperation whose parameter is being written.

Definition at line 1062 of file DataDependenceGraphBuilder.cc.

1063 {
1064
1065 // first operands already analyzed for PO?
1066 // then update existing.
1067 if (currentData_->destPending_ != NULL) {
1069
1070 assert(&dop == &po->operation());
1071
1072 if (!po->isComplete()) {
1073 po->addInputNode(moveNode);
1074 moveNode.addDestinationOperationPtr(po);
1075 } else {
1076 // The MoveNode and the PO has been created before entering DDG
1077 // building (in LLVMTCEBuilder.cc).
1078 }
1079 return;
1080 }
1081
1082 // create a new ProgramOperation
1083 TerminalFUPort& tfpd =
1084 dynamic_cast<TerminalFUPort&>(moveNode.move().destination());
1086 if (tfpd.hasProgramOperation()) {
1087 po = tfpd.programOperation();
1088 } else {
1090 moveNode.addDestinationOperationPtr(po);
1091 po->addInputNode(moveNode);
1092 }
1094}
bool hasProgramOperation() const
these methods are used to group terminals belonging to a single program operation invocation
ProgramOperationPtr programOperation() const

References MoveNode::addDestinationOperationPtr(), assert, currentData_, TTAProgram::Move::destination(), DataDependenceGraphBuilder::BBData::destPending_, TTAProgram::TerminalFUPort::hasProgramOperation(), MoveNode::move(), and TTAProgram::TerminalFUPort::programOperation().

Referenced by processDestination().

Here is the call graph for this function:

◆ processRegUse()

void DataDependenceGraphBuilder::processRegUse ( MoveNodeUse  mnd,
const TCEString reg 
)
protected

Handles a usage of a register value.

The usage can be either register read or guard usage. Creates the incoming edges and handles bookkeping related to the register read.

Parameters
mndData about the register use
regRegister containing the value being used.

Definition at line 1229 of file DataDependenceGraphBuilder.cc.

1230 {
1231
1232 // We may have multiple definitions to a register alive
1233 // (statically) at same time if some of the writes were guarded,
1234 // so we don't know which of them were actually executed,
1235 // so we have a set instead of single value.
1236 std::set<MoveNodeUse>& defines =
1238
1239 std::set<MoveNodeUse> sameGuardDefines = earlierWritesWithSameGuard(mnd, defines);
1240 // find if we have a earlier write with same guard. In this case
1241 // no need to draw dependencies over it.
1242 bool guardedKillFound = !sameGuardDefines.empty();
1243
1244 // then create the edges. if no guarded kill found,
1245 // all non-exclusive. if guarded kill found, not to uncond move.
1246 for (std::set<MoveNodeUse>::iterator i = defines.begin();
1247 i != defines.end(); i++) {
1248 // If we do not have a guarded kill, draw edges from all defines.
1249 // If we have a guarded kill, only draw edges from
1250 // unconditional moves, as the guarded kill overshadows the
1251 // inconditional writes.
1252 if (!guardedKillFound || (!i->mn()->move().isUnconditional() &&
1253 !currentDDG_->hasRegWaw(*i, sameGuardDefines))) {
1254 if (!currentDDG_->exclusingGuards(*(i->mn()), *(mnd.mn()))) {
1255 DataDependenceEdge* dde =
1258 DataDependenceEdge::EDGE_REGISTER,
1259 DataDependenceEdge::DEP_RAW, reg, mnd.guard(), false,
1260 i->pseudo(), mnd.pseudo(), i->loop());
1261
1262 currentDDG_->connectOrDeleteEdge(*i->mn(), *mnd.mn(), dde);
1263 }
1264 }
1265 }
1266
1267 // writes in previous BB's killed or not?
1268 // if not(this bb has a kill), has to check deps from incoming BB's.
1269 if (currentBB_->basicBlock().liveRangeData_->regKills_.find(reg) ==
1271
1272 if (!guardedKillFound) {
1273 // process dependencies from previous BB's
1275 insert(mnd);
1276
1278 }
1279 }
1280 currentBB_->basicBlock().liveRangeData_->regLastUses_[reg].insert(mnd);
1281
1282 // Two writes to opposite guard may create a combined kill-pair.
1283 // But if this is a read between them, it has to be marked in order
1284 // to save bookkeeping about this move when the another write occurs.
1285 // So mark here that we have a read if we have one guarded write
1286 // in our bookkeeping as potential half of a kill pair.
1287 std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator iter =
1290 iter->second.second = true;
1291 }
1292}
std::set< MoveNodeUse > earlierWritesWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
bool hasRegWaw(const MoveNodeUse &mnu, std::set< MoveNodeUse > targets) const

References BasicBlockNode::basicBlock(), DataDependenceGraph::connectOrDeleteEdge(), currentBB_, currentDDG_, DataDependenceEdge::DEP_RAW, earlierWritesWithSameGuard(), DataDependenceEdge::EDGE_RA, DataDependenceEdge::EDGE_REGISTER, DataDependenceGraph::exclusingGuards(), MoveNodeUse::guard(), DataDependenceGraph::hasRegWaw(), TTAProgram::BasicBlock::liveRangeData_, MoveNodeUse::mn(), LiveRangeData::potentialRegKills_, MoveNodeUse::pseudo(), MoveNodeUse::ra(), LiveRangeData::regDefines_, LiveRangeData::regFirstUses_, LiveRangeData::regKills_, LiveRangeData::regLastUses_, and DataDependenceGraph::updateRegUse().

Referenced by processCall(), processGuard(), processReturn(), and processSource().

Here is the call graph for this function:

◆ processRegWrite()

void DataDependenceGraphBuilder::processRegWrite ( MoveNodeUse  mnd,
const TCEString reg 
)
protected

Analyzes a write to a register.

Creates dependence edges and updates bookkeeping.

Parameters
mndMoveNodeUse containing MoveNode that writes a register
regregister being written by the given movenode.

Definition at line 1369 of file DataDependenceGraphBuilder.cc.

1370 {
1371
1372 // We may have multiple definitions to a register alive
1373 // (statically) at same time if some of the writes were guarded,
1374 // so we don't know which of them were actually executed,
1375 // so we have a set instead of single value.
1376 std::set<MoveNodeUse>& defines =
1378
1379 // Set of register reads which after last kill.
1380 std::set<MoveNodeUse>& lastUses =
1382
1383 // find if we have a earlier write with same guard. In this case
1384 // no need to draw dependencies over it.
1385 bool guardedKillFound = hasEarlierWriteWithSameGuard(mnd, defines);
1386
1387 // if no kills to this reg in this BB, this one kills it.
1388 if (currentBB_->basicBlock().liveRangeData_->regKills_.find(reg) ==
1390
1391 // is this alone a kill?
1392 if (mnd.mn()->move().isUnconditional()) {
1393 currentBB_->basicBlock().liveRangeData_->regKills_[reg].first = mnd;
1395 } else {
1396 // two guarded moves with opposite guards together may be a kill.
1397 // Check if we have such previous guarded write with opposite
1398 // guard.
1399 std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator
1400 iter =
1404 *(iter->second.first.mn()), *(mnd.mn()))) {
1406 iter->second.first;
1407 currentBB_->basicBlock().liveRangeData_->regKills_[reg].second = mnd;
1408 }
1409 }
1410 if (!guardedKillFound) {
1411 // may have incoming WaW's / WaRs to this
1412 // insert to bookkeeping for further analysis.
1414
1415 // do we need to create some inter-bb-antideps?
1417 // deps from other BB.LIVERANGEDATA_->
1419 mnd, reg, currentBB_->basicBlock());
1420 }
1421 }
1422 }
1423
1424 // Create antideps to defines and uses in this same BB.LIVERANGEDATA_->
1427 reg, mnd, defines, DataDependenceEdge::DEP_WAW, guardedKillFound);
1428
1430 reg, mnd, lastUses, DataDependenceEdge::DEP_WAR,
1431 guardedKillFound);
1432 }
1433
1434 // if unconditional, this kills previous deps.
1435 if (mnd.mn()->move().isUnconditional()) {
1436 defines.clear();
1437
1440
1441 // clear reads to given reg.
1442 lastUses.clear();
1444 } else {
1445 // two guarded moves with opposite guards together may be a kill.
1446 // Check if we have such previous guarded write with opposite
1447 // guard.
1448 std::map<TCEString, std::pair<MoveNodeUse, bool> >::iterator iter =
1452 *(iter->second.first.mn()), *(mnd.mn()))) {
1453
1454 // found earlier write which is exclusive with this one.
1455 // mark that these two together are a kill.
1457 iter->second.first;
1458 currentBB_->basicBlock().liveRangeData_->regLastKills_[reg].second = mnd;
1459
1460 // If we have no usage of the register between these two
1461 // writes forming the kill pair, we can clear our bookkeeping.
1462
1463 // only leave the other part of the kill to defines.
1464 defines.clear();
1465 defines.insert(iter->second.first);
1466
1467 if (!iter->second.second) {
1468 // clear reads to given reg.
1469 lastUses.clear();
1470 }
1471 }
1473 std::pair<MoveNodeUse, bool>(mnd, false);
1474 }
1475 defines.insert(mnd);
1476}
void createRegisterAntideps(const TCEString &reg, MoveNodeUse &mnd, MoveNodeUseSet &predecessorNodes, DataDependenceEdge::DependenceType depType, bool guardedKillFound)
bool hasEarlierWriteWithSameGuard(MoveNodeUse &mnd, std::set< MoveNodeUse > &defines)
DataDependenceGraph::EdgeSet updateRegWrite(const MoveNodeUse &mnd, const TCEString &reg, TTAProgram::BasicBlock &bb)

References BasicBlockNode::basicBlock(), createRegisterAntideps(), currentBB_, currentDDG_, DataDependenceEdge::DEP_WAR, DataDependenceEdge::DEP_WAW, DataDependenceGraph::exclusingGuards(), hasEarlierWriteWithSameGuard(), DataDependenceGraph::hasIntraBBRegisterAntidependencies(), DataDependenceGraph::hasSingleBBLoopRegisterAntidependencies(), TTAProgram::Move::isUnconditional(), TTAProgram::BasicBlock::liveRangeData_, MoveNodeUse::mn(), MoveNode::move(), LiveRangeData::potentialRegKills_, LiveRangeData::regDefines_, LiveRangeData::regFirstDefines_, LiveRangeData::regKills_, LiveRangeData::regLastKills_, LiveRangeData::regLastUses_, and DataDependenceGraph::updateRegWrite().

Referenced by processCall(), and processDestination().

Here is the call graph for this function:

◆ processResultRead()

void DataDependenceGraphBuilder::processResultRead ( MoveNode moveNode)
protected

Analyzes a source of a result read.

Handles program operation creation and operation dependence creation.

Parameters
moveNodeMoveNode of the move being analyzed.

Definition at line 1104 of file DataDependenceGraphBuilder.cc.

1104 {
1105
1106 // Goes thru all programoperations lacking result read.
1107 // There should be only one if well-behaving
1108 // universalmachine code.
1109 if (currentData_->readPending_ != NULL) {
1112
1113 if (!po->isComplete()) {
1114 po->addOutputNode(moveNode);
1115 moveNode.setSourceOperationPtr(po);
1116 }
1117
1118 // if this PO is ready, remove from list of incomplete ones
1120 po->operation().numberOfOutputs()) {
1125 }
1126 return;
1127 }
1128 throw IllegalProgram(
1129 __FILE__, __LINE__, __func__,
1130 (boost::format("Result move '%s' without operands") %
1131 moveNode.move().toString()).str());
1132}
void createOperationEdges(ProgramOperationPtr po)
void addProgramOperation(ProgramOperationPtr po)
void setSourceOperationPtr(ProgramOperationPtr po)
Definition MoveNode.cc:541
std::string toString() const
Definition Move.cc:436

References __func__, DataDependenceGraph::addProgramOperation(), createOperationEdges(), currentData_, currentDDG_, MoveNode::move(), DataDependenceGraphBuilder::BBData::poReadsHandled_, DataDependenceGraphBuilder::BBData::readPending_, MoveNode::setSourceOperationPtr(), and TTAProgram::Move::toString().

Referenced by processSource().

Here is the call graph for this function:

◆ processReturn()

void DataDependenceGraphBuilder::processReturn ( MoveNode moveNode)
protected

Processes a return from a function.

Creates pseudo-read-deps to SP and RV registers.

Parameters
moveNodemoveNode containg the return move.

Definition at line 1486 of file DataDependenceGraphBuilder.cc.

1486 {
1488
1489 // return is considered as read of sp;
1490 // sp must be correct at the end of the procedure.
1491 if (sp != "") {
1492 processRegUse(MoveNodeUse(moveNode,false,false,true),sp);
1493 }
1494
1495 // return is considered as read of RV.
1497 if (rv != "") {
1498 processRegUse(MoveNodeUse(moveNode,false,false,true),rv);
1499 }
1500
1501 // process all vector rv values
1502 for (int i = REG_VRV;;i--) {
1503 auto vrvIt = specialRegisters_.find(i);
1504 if (vrvIt != specialRegisters_.end()) {
1506 MoveNodeUse(moveNode,false,false,true),vrvIt->second);
1507 } else {
1508 break;
1509 }
1510 }
1511
1512 // return is also considered as read of RV high(for 64-bit RV's)
1514 if (rvh != "") {
1515 processRegUse(MoveNodeUse(moveNode,false,false,true),rvh);
1516 }
1517
1519 if (fp != "") {
1520 processRegUse(MoveNodeUse(moveNode,false,false,true),fp);
1521 }
1522}

References processRegUse(), REG_FP, REG_RV, REG_RV_HIGH, REG_SP, REG_VRV, and specialRegisters_.

Referenced by processSource().

Here is the call graph for this function:

◆ processSource()

void DataDependenceGraphBuilder::processSource ( MoveNode moveNode)
protected

Analysis a source of a move and processes it's dependencies, and if it's a result read then also participates in ProgramOperation creation.

Parameters
moveNodeMovenode being analyzed.

Definition at line 785 of file DataDependenceGraphBuilder.cc.

785 {
786 Terminal& source = moveNode.move().source();
787
788 // is this result move of an operation?
789 if (source.isFUPort()) {
790 if (!(dynamic_cast<const SpecialRegisterPort*>(&source.port()))) {
791 processResultRead(moveNode);
792 } else {
793 // handle read from RA.
794 processRegUse(MoveNodeUse(moveNode, false, true), RA_NAME);
795
796 if (moveNode.move().isReturn()) {
797 processReturn(moveNode);
798 }
799 }
800 } else {
801 if (source.isGPR()) {
802 TerminalRegister& tr = dynamic_cast<TerminalRegister&>(source);
804 processRegUse(MoveNodeUse(moveNode), regName);
805 }
806 }
807}
void processResultRead(MoveNode &moveNode)
bool isReturn() const
Definition Move.cc:259

References TTAProgram::Terminal::isFUPort(), TTAProgram::Terminal::isGPR(), TTAProgram::Move::isReturn(), MoveNode::move(), TTAProgram::Terminal::port(), processRegUse(), processResultRead(), processReturn(), RA_NAME, DisassemblyRegister::registerName(), and TTAProgram::Move::source().

Referenced by constructIndividualBB().

Here is the call graph for this function:

◆ processTriggerMemoryAndFUStates()

void DataDependenceGraphBuilder::processTriggerMemoryAndFUStates ( MoveNode moveNode,
Operation dop 
)
protected

Analyze write to a trigger of an operation.

Participates in ProgramOperation building. Calls createTriggerDependencies(moveNode, dop) to create the memory and fu state dependence egdes of the operation. Checks if operation is call and if it is, processes the call-related memory dependencies.

Parameters
moveNodemnData related to a move which triggers an operation
dopOperation being triggered

Definition at line 1040 of file DataDependenceGraphBuilder.cc.

1041 {
1042
1043 createTriggerDependencies(moveNode, dop);
1044
1045 // handle call mem deps
1046 if (moveNode.move().isFunctionCall()) {
1047 // no guard, is not ra, is pseudo.
1048 MoveNodeUse mnd2(moveNode, false, false, true);
1049 processMemWrite(mnd2);
1050 }
1051}
void createTriggerDependencies(class MoveNode &moveNode, class Operation &dop)
bool isFunctionCall() const
Definition Move.cc:219

References createTriggerDependencies(), TTAProgram::Move::isFunctionCall(), MoveNode::move(), and processMemWrite().

Referenced by processDestination().

Here is the call graph for this function:

◆ processTriggerPO()

void DataDependenceGraphBuilder::processTriggerPO ( class MoveNode moveNode,
Operation dop 
)
protected

Handles ProgramOperation creation for a triggering move.

Parameters
moveNodetriggering movenode.
dopoperation which is being triggered by the movenode.

Definition at line 948 of file DataDependenceGraphBuilder.cc.

949 {
950 if (currentData_->destPending_ != NULL) {
952
953 if (&dop != &po->operation()) {
954 std::cerr << "pending po: " << po->toString() << std::endl;
955 std::cerr << "current dop: " << dop.name() << std::endl;
956 currentDDG_->writeToDotFile("build_fail_po.dot");
957 }
958 assert(&dop == &po->operation());
959 if (!po->isComplete()) {
960 po->addInputNode(moveNode);
961 moveNode.addDestinationOperationPtr(po);
962 }
963 if (po->isReady()) {
965 if (dop.numberOfOutputs() > 0) {
969 } else {
971 }
972 } else {
973 throw IllegalProgram(
974 __FILE__, __LINE__, __func__,
975 "Trigger before all operands.");
976 }
977 return;
978 }
979 // only one triggering input?
980 if (dop.numberOfInputs() == 1) {
981 TerminalFUPort& tfpd =
982 dynamic_cast<TerminalFUPort&>(moveNode.move().destination());
984 if (tfpd.hasProgramOperation()) {
985 po = tfpd.programOperation();
986 } else {
988 moveNode.addDestinationOperationPtr(po);
989 po->addInputNode(moveNode);
990 }
991 if (dop.numberOfOutputs()) {
994 } else {
996 }
997 } else { // trigger came too early
998 const TCEString moveDisasm =
999 POMDisassembler::disassemble(moveNode.move());
1000 throw IllegalProgram(
1001 __FILE__,__LINE__, __func__,
1002 TCEString("Trigger without operand in ") + moveDisasm);
1003 }
1004}
virtual int numberOfInputs() const
Definition Operation.cc:192
virtual int numberOfOutputs() const
Definition Operation.cc:202
static std::string disassemble(const TTAProgram::Move &move)

References __func__, MoveNode::addDestinationOperationPtr(), DataDependenceGraph::addProgramOperation(), assert, currentData_, currentDDG_, TTAProgram::Move::destination(), DataDependenceGraphBuilder::BBData::destPending_, POMDisassembler::disassemble(), TTAProgram::TerminalFUPort::hasProgramOperation(), MoveNode::move(), Operation::name(), Operation::numberOfInputs(), Operation::numberOfOutputs(), DataDependenceGraphBuilder::BBData::poReadsHandled_, TTAProgram::TerminalFUPort::programOperation(), DataDependenceGraphBuilder::BBData::readPending_, and GraphBase< GraphNode, GraphEdge >::writeToDotFile().

Referenced by processTriggerRegistersAndOperations().

Here is the call graph for this function:

◆ processTriggerRegistersAndOperations()

void DataDependenceGraphBuilder::processTriggerRegistersAndOperations ( MoveNode moveNode,
Operation dop 
)
protected

Analyze write to a trigger of an operation.

Participates in ProgramOperation building. Calls createTriggerDependencies(moveNode, dop) to create the register and operation dependence egdes of the operation. Checks if operation is call and if it is, processes the call-related register dependencies.

Parameters
moveNodemnData related to a move which triggers an operation
dopOperation being triggered

Definition at line 1018 of file DataDependenceGraphBuilder.cc.

1019 {
1020
1021 processTriggerPO(moveNode, dop);
1022
1023 if (moveNode.move().isFunctionCall()) {
1024 processCall(moveNode);
1025 }
1026}
void processTriggerPO(class MoveNode &moveNode, Operation &dop)

References TTAProgram::Move::isFunctionCall(), MoveNode::move(), processCall(), and processTriggerPO().

Referenced by processDestination().

Here is the call graph for this function:

◆ queueFirstBB()

BasicBlockNode * DataDependenceGraphBuilder::queueFirstBB ( )
protected

Queues first basic block to be processed.

Returns
the first basic block node

Definition at line 2238 of file DataDependenceGraphBuilder.cc.

2238 {
2239 // get first BB where to start
2241 assert(firstBBs.size() == 1);
2242 BasicBlockNode* firstBB = *firstBBs.begin();
2243 changeState(*(bbData_[firstBB]), BB_QUEUED);
2244 return firstBB;
2245}
virtual NodeSet successors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
ControlFlowGraph::NodeSet BasicBlockNodeSet

References assert, BB_QUEUED, bbData_, cfg_, changeState(), ControlFlowGraph::entryNode(), and BoostGraph< GraphNode, GraphEdge >::successors().

Referenced by createMemAndFUstateDeps(), and createRegisterDeps().

Here is the call graph for this function:

◆ searchRegisterDeaths()

void DataDependenceGraphBuilder::searchRegisterDeaths ( )
protected

Searches the last usages a registers.

This information is used for checking whether given register contains live value at given cycle.

Definition at line 2882 of file DataDependenceGraphBuilder.cc.

2882 {
2883
2884 // initializes states of all BB's to unreached.
2886
2887 // start from end of cfg. (sink nodes), queue them
2889 for (ControlFlowGraph::NodeSet::iterator iter =
2890 lastBBs.begin(); iter != lastBBs.end(); iter++) {
2891 changeState(*(bbData_[*iter]), BB_QUEUED);
2892 }
2893
2894 // then iterate over all BB's, going from BB to it's
2895 // predecessors.
2897
2898 // all should have gone thru, but if there are 4ever loop causing
2899 // BB's not reachable from the end.
2900 // we might want to handle those also.
2901 while (!blocksByState_[BB_UNREACHED].empty()) {
2903 Application::logStream() << "Warning: BB in 4ever loop!"
2904 << std::endl;
2905 Application::logStream() << "In procedure: " << cfg_->name() <<
2906 std::endl;
2907// cfg.writeToDotFile("4everloop_bb.dot");
2908 }
2910
2912 }
2913
2914 // free bb data
2916}
virtual NodeSet sinkNodes() const
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53

References BB_QUEUED, BB_UNREACHED, bbData_, blocksByState_, cfg_, changeState(), AssocTools::deleteAllValues(), initializeBBStates(), iterateRegisterDeaths(), Application::logStream(), BoostGraph< GraphNode, GraphEdge >::name(), BoostGraph< GraphNode, GraphEdge >::sinkNodes(), Application::VERBOSE_LEVEL_DEFAULT, and Application::verboseLevel().

Referenced by build().

Here is the call graph for this function:

◆ setSucceedingPredeps()

void DataDependenceGraphBuilder::setSucceedingPredeps ( BBData bbd,
bool  queueAll,
ConstructionPhase  phase 
)
protected

Sets outgoing data from this BB to incoming data of successors.

Also queues them to be reprocessed if they are changed.

Parameters
bbdBBD whose successors will be updated.
queueAllIf true, queues all successors even if they do not change.
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 2424 of file DataDependenceGraphBuilder.cc.

2426 {
2427 BasicBlockNode& bbn = *bbd.bblock_;
2428 BasicBlock& bb = bbn.basicBlock();
2429
2430 BasicBlockNodeSet forwardSuccessors = cfg_->successors(bbn, true);
2431 for (BasicBlockNodeSet::iterator succIter = forwardSuccessors.begin();
2432 succIter != forwardSuccessors.end(); succIter++) {
2434 bb, **succIter, queueAll, false, phase);
2435 }
2436
2437 // successors over loop edges.
2438 BasicBlockNodeSet backwardSuccessors = cfg_->successors(bbn, false, true);
2439 for (BasicBlockNodeSet::iterator succIter = backwardSuccessors.begin();
2440 succIter != backwardSuccessors.end(); succIter++) {
2442 bb, **succIter, queueAll, true, phase);
2443 }
2444}
void setSucceedingPredepsForBB(TTAProgram::BasicBlock &processedBB, BasicBlockNode &successor, bool queueAll, bool loop, ConstructionPhase phase)

References BasicBlockNode::basicBlock(), DataDependenceGraphBuilder::BBData::bblock_, cfg_, setSucceedingPredepsForBB(), and BoostGraph< GraphNode, GraphEdge >::successors().

Referenced by iterateBBs().

Here is the call graph for this function:

◆ setSucceedingPredepsForBB()

void DataDependenceGraphBuilder::setSucceedingPredepsForBB ( TTAProgram::BasicBlock processedBB,
BasicBlockNode successor,
bool  queueAll,
bool  loop,
ConstructionPhase  phase 
)
protected

Sets outgoing data from this BB to incoming data of one successor.

Also queues them to be reprocessed if they are changed.

Parameters
bbBB whose successor will be updated.
successorsuccessor BB whose incoming data is being updated.
queueAllIf true, queues all successors even if they do not change.
loopwhether to add loop property to the copied bookkeeping, ie create edges with loop property.
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 2460 of file DataDependenceGraphBuilder.cc.

2462 {
2463
2464 BasicBlock& succBB = successor.basicBlock();
2465 BBData& succData = *bbData_[&successor];
2466 bool changed = false;
2467
2468 if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2470 bb.liveRangeData_->regDefAfter_,
2471 succBB.liveRangeData_->regDefReaches_, loop);
2472
2474 (&bb == &succBB &&
2477 bb.liveRangeData_->regUseAfter_,
2478 succBB.liveRangeData_->regUseReaches_, loop);
2479 }
2480 } else {
2481 // mem deps + fu state deps
2482
2484 bb.liveRangeData_->memDefAfter_,
2485 succBB.liveRangeData_->memDefReaches_, loop);
2486
2488 bb.liveRangeData_->memUseAfter_,
2489 succBB.liveRangeData_->memUseReaches_, loop);
2490
2491 size_t size = succBB.liveRangeData_->fuDepReaches_.size();
2493 bb.liveRangeData_->fuDepAfter_,
2494 succBB.liveRangeData_->fuDepReaches_, loop);
2495 if (succBB.liveRangeData_->fuDepReaches_.size() > size) {
2496 changed = true;
2497 }
2498 }
2499
2500 // need to queue successor for update?
2501 if (changed || queueAll) {
2502 changeState(succData, BB_QUEUED, loop);
2503 }
2504}
static bool appendUseMapSets(const MoveNodeUseMapSet &srcMap, MoveNodeUseMapSet &dstMap, bool addLoopProperty)
static void appendMoveNodeUse(const MoveNodeUseSet &src, MoveNodeUseSet &dst, bool setLoopProperty)

References LiveRangeData::appendMoveNodeUse(), LiveRangeData::appendUseMapSets(), BasicBlockNode::basicBlock(), BB_QUEUED, bbData_, changeState(), currentDDG_, LiveRangeData::fuDepAfter_, LiveRangeData::fuDepReaches_, DataDependenceGraph::hasAllRegisterAntidependencies(), DataDependenceGraph::hasSingleBBLoopRegisterAntidependencies(), TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefAfter_, LiveRangeData::memDefReaches_, LiveRangeData::memUseAfter_, LiveRangeData::memUseReaches_, LiveRangeData::regDefAfter_, LiveRangeData::regDefReaches_, REGISTERS_AND_PROGRAM_OPERATIONS, LiveRangeData::regUseAfter_, and LiveRangeData::regUseReaches_.

Referenced by setSucceedingPredeps().

Here is the call graph for this function:

◆ updateBB()

void DataDependenceGraphBuilder::updateBB ( BBData bbd,
ConstructionPhase  phase 
)
protected

Reprocesses a basic block which has already once been processed.

Checks dependencies to first uses and definitions of registers, does not recreate edges inside the basic block.

Parameters
bbdBBData for basic block which is being reprocessed.
phasewhether to handle register& operation deps or memory and side-effect dependencies.

Definition at line 2743 of file DataDependenceGraphBuilder.cc.

2744 {
2745 currentData_ = &bbd;
2746 currentBB_ = bbd.bblock_;
2747 BasicBlock& bb = bbd.bblock_->basicBlock();
2748
2749 // register and operation dependencies
2750 if (phase == REGISTERS_AND_PROGRAM_OPERATIONS) {
2751 //loop all regs having ext deps and create reg edges
2752 for (MoveNodeUseMapSet::iterator firstUseIter =
2753 bb.liveRangeData_->regFirstUses_.begin();
2754 firstUseIter != bb.liveRangeData_->regFirstUses_.end();
2755 firstUseIter++) {
2756 TCEString reg = firstUseIter->first;
2757 std::set<MoveNodeUse>& firstUseSet = firstUseIter->second;
2758 for (std::set<MoveNodeUse>::iterator iter2 = firstUseSet.begin();
2759 iter2 != firstUseSet.end(); iter2++) {
2761 *iter2, reg, currentBB_->basicBlock());
2762 }
2763 }
2764
2766 // antidependencies to registers
2767 for (MoveNodeUseMapSet::iterator firstDefineIter =
2768 bb.liveRangeData_->regFirstDefines_.begin();
2769 firstDefineIter != bb.liveRangeData_->regFirstDefines_.end();
2770 firstDefineIter++) {
2771 TCEString reg = firstDefineIter->first;
2772 std::set<MoveNodeUse>& firstDefineSet =
2773 firstDefineIter->second;
2774 for (std::set<MoveNodeUse>::iterator iter2=
2775 firstDefineSet.begin();
2776 iter2 != firstDefineSet.end(); iter2++) {
2778 *iter2, reg, currentBB_->basicBlock());
2779 }
2780 }
2781 }
2782 } else {
2783 // phase 1 .. mem deps and fu state/side effect dependencies.
2784
2785 //loop all first mem uses having ext deps and create mem edges
2786 for (MoveNodeUseMapSet::iterator firstUseIter =
2787 bb.liveRangeData_->memFirstUses_.begin();
2788 firstUseIter != bb.liveRangeData_->memFirstUses_.end();
2789 firstUseIter++) {
2790 TCEString category = firstUseIter->first;
2791 std::set<MoveNodeUse>& firstUseSet = firstUseIter->second;
2792 for (std::set<MoveNodeUse>::iterator iter2 = firstUseSet.begin();
2793 iter2 != firstUseSet.end(); iter2++) {
2794 updateMemUse(*iter2, category);
2795 }
2796 }
2797
2798 // antidependencies to memory
2799 for (MoveNodeUseMapSet::iterator firstDefineIter =
2800 bb.liveRangeData_->memFirstDefines_.begin();
2801 firstDefineIter != bb.liveRangeData_->memFirstDefines_.end();
2802 firstDefineIter++) {
2803 TCEString category = firstDefineIter->first;
2804 std::set<MoveNodeUse>& firstDefineSet = firstDefineIter->second;
2805 for (std::set<MoveNodeUse>::iterator iter2=firstDefineSet.begin();
2806 iter2 != firstDefineSet.end(); iter2++) {
2807 updateMemWrite(*iter2, category);
2808 }
2809 }
2810
2811 // and fu state deps
2812 for (MoveNodeUseSet::iterator iter =
2813 bb.liveRangeData_->fuDeps_.begin();
2814 iter != bb.liveRangeData_->fuDeps_.end(); iter++) {
2815 Terminal& dest = iter->mn()->move().destination();
2816 TerminalFUPort& tfpd = dynamic_cast<TerminalFUPort&>(dest);
2817 Operation &dop = tfpd.hintOperation();
2820 *iter->mn(), dop);
2821 }
2822 }
2823}

References BasicBlockNode::basicBlock(), DataDependenceGraphBuilder::BBData::bblock_, createSideEffectEdges(), currentBB_, currentData_, currentDDG_, LiveRangeData::fuDepReaches_, LiveRangeData::fuDeps_, DataDependenceGraph::hasSingleBBLoopRegisterAntidependencies(), TTAProgram::TerminalFUPort::hintOperation(), TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memFirstDefines_, LiveRangeData::memFirstUses_, LiveRangeData::regFirstDefines_, LiveRangeData::regFirstUses_, REGISTERS_AND_PROGRAM_OPERATIONS, updateMemUse(), updateMemWrite(), DataDependenceGraph::updateRegUse(), and DataDependenceGraph::updateRegWrite().

Referenced by iterateBBs().

Here is the call graph for this function:

◆ updateMemAndFuAliveAfter()

bool DataDependenceGraphBuilder::updateMemAndFuAliveAfter ( BBData bbd)
protected

Updates live mem access lists and fu state usages after a basic block has been processed.

Copies use and write definitions from the basic block and it's prodecessors to the after alive data structures.

Parameters
bbdBBData for bb being processed
Returns
true if the after alive data structures have been changed

Definition at line 2592 of file DataDependenceGraphBuilder.cc.

2592 {
2593 BasicBlock& bb = bbd.bblock_->basicBlock();
2594 bool changed = false;
2595
2596 // copy mem definitions that are alive
2597 for (MoveNodeUseMapSet::iterator iter = bb.liveRangeData_->memDefReaches_.begin();
2598 iter != bb.liveRangeData_->memDefReaches_.end(); iter++) {
2599
2600 TCEString category = iter->first;
2601 std::set<MoveNodeUse>& preDefs = iter->second;
2602 std::set<MoveNodeUse>& defAfter = bb.liveRangeData_->memDefAfter_[category];
2603 std::set<MoveNodeUse>& ownDefines = bb.liveRangeData_->memDefines_[category];
2604 size_t size = defAfter.size();
2605
2606 // only copy incomin dep if this has no unconditional writes,
2607 if (bb.liveRangeData_->memKills_.find(category) == bb.liveRangeData_->memKills_.end()) {
2608 for (std::set<MoveNodeUse>::iterator i = preDefs.begin();
2609 i != preDefs.end(); i++ ) {
2610// MoveNode* preAddress = addressMove(*(i->mn()));
2611 ProgramOperation& prevPop = i->mn()->destinationOperation();
2612
2613 bool overWritten = false;
2614 for (std::set<MoveNodeUse>::iterator j = ownDefines.begin();
2615 j != ownDefines.end(); j++) {
2616 if (j->mn()->move().isUnconditional()) {
2617// MoveNode* ownAddress = addressMove(*(j->mn()));
2618 ProgramOperation& ownPop = j->mn()->destinationOperation();
2619 if (analyzeMemoryAlias(prevPop, ownPop, i->bbRelation()) ==
2621 overWritten = true;
2622 break;
2623 }
2624 }
2625 }
2626 if (!overWritten) {
2627 defAfter.insert(*i);
2628 }
2629 }
2630 }
2631 // if size increased, the data has changed
2632 if (size < defAfter.size()) {
2633 changed = true;
2634 }
2635 }
2636 // own deps. need to do only once but now does after every.
2639 bb.liveRangeData_->memDefAfter_, false);
2640
2641 // copy uses that are alive
2642 for (MoveNodeUseMapSet::iterator iter = bb.liveRangeData_->memUseReaches_.begin();
2643 iter != bb.liveRangeData_->memUseReaches_.end(); iter++) {
2644
2645 TCEString category = iter->first;
2646 std::set<MoveNodeUse>& preUses = iter->second;
2647 std::set<MoveNodeUse>& useAfter = bb.liveRangeData_->memUseAfter_[category];
2648 std::set<MoveNodeUse>& ownDefines = bb.liveRangeData_->memDefines_[category];
2649
2650 size_t size = useAfter.size();
2651 if (bb.liveRangeData_->memKills_.find(category) == bb.liveRangeData_->memKills_.end()) {
2652 for (std::set<MoveNodeUse>::iterator i = preUses.begin();
2653 i != preUses.end(); i++ ) {
2654// MoveNode* preAddress = addressMove(*(i->mn()));
2655 ProgramOperation& prevPop = i->mn()->destinationOperation();
2656 bool overWritten = false;
2657 for (std::set<MoveNodeUse>::iterator j =
2658 ownDefines.begin(); j != ownDefines.end(); j++) {
2659 if (j->mn()->move().isUnconditional()) {
2660 ProgramOperation& ownPop = j->mn()->destinationOperation();
2661 if (analyzeMemoryAlias(prevPop, ownPop, i->bbRelation()) ==
2663 overWritten = true;
2664 break;
2665 }
2666 }
2667 }
2668 if (!overWritten) {
2669 useAfter.insert(*i);
2670 }
2671 }
2672 }
2673 // if size increased, the data has changed
2674 if (size < useAfter.size()) {
2675 changed = true;
2676 }
2677 }
2678
2679 // fu deps
2680 size_t size = bb.liveRangeData_->fuDepAfter_.size();
2682 if (bb.liveRangeData_->fuDepAfter_.size() > size) {
2683 changed = true;
2684 }
2685 return changed;
2686}
static void append(const ContainerType &src, ContainerType &dest)
MoveNodeUseMapSet memDefAfter_
MoveNodeUseMapSet memUseAfter_

References MemoryAliasAnalyzer::ALIAS_TRUE, analyzeMemoryAlias(), AssocTools::append(), LiveRangeData::appendUseMapSets(), BasicBlockNode::basicBlock(), DataDependenceGraphBuilder::BBData::bblock_, LiveRangeData::fuDepAfter_, LiveRangeData::fuDeps_, TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefAfter_, LiveRangeData::memDefines_, LiveRangeData::memDefReaches_, LiveRangeData::memKills_, LiveRangeData::memUseAfter_, and LiveRangeData::memUseReaches_.

Referenced by iterateBBs().

Here is the call graph for this function:

◆ updateMemUse()

void DataDependenceGraphBuilder::updateMemUse ( MoveNodeUse  mnd,
const TCEString category 
)
protected

Checks memory read against uses and defs in incoming basic blocks. Creates the needed dependence edges.

Parameters
mndMoveNodeUse of movenode being processed.
categorywhich memory category this memory write belongs.

Definition at line 2859 of file DataDependenceGraphBuilder.cc.

2860 {
2861
2862 for (MoveNodeUseSet::iterator iter =
2863 currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].begin();
2864 iter != currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].end();
2865 iter++) {
2867 }
2868}

References BasicBlockNode::basicBlock(), checkAndCreateMemDep(), currentBB_, DataDependenceEdge::DEP_RAW, TTAProgram::BasicBlock::liveRangeData_, and LiveRangeData::memDefReaches_.

Referenced by processMemUse(), and updateBB().

Here is the call graph for this function:

◆ updateMemWrite()

void DataDependenceGraphBuilder::updateMemWrite ( MoveNodeUse  mnd,
const TCEString category 
)
protected

Checks memory write against uses and defs in incoming basic blocks. Creates the needed dependence edges.

Parameters
mndMoveNodeUse of movenode being processed.
categorywhich memory category this memory write belongs.

Definition at line 2833 of file DataDependenceGraphBuilder.cc.

2834 {
2835
2836 // create waw edges from all alive writes to this node.
2837 for (MoveNodeUseSet::iterator iter =
2838 currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].begin();
2839 iter != currentBB_->basicBlock().liveRangeData_->memDefReaches_[category].end();) {
2841 }
2842
2843 // create war edges from all alive reads to this node.
2844 for (MoveNodeUseSet::iterator iter = currentBB_->basicBlock().liveRangeData_->
2845 memUseReaches_[category].begin();
2846 iter != currentBB_->basicBlock().liveRangeData_->memUseReaches_[category].end();) {
2848 }
2849}

References BasicBlockNode::basicBlock(), checkAndCreateMemDep(), currentBB_, DataDependenceEdge::DEP_WAR, DataDependenceEdge::DEP_WAW, TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::memDefReaches_, and LiveRangeData::memUseReaches_.

Referenced by processMemWrite(), and updateBB().

Here is the call graph for this function:

◆ updatePreceedingRegistersUsedAfter()

void DataDependenceGraphBuilder::updatePreceedingRegistersUsedAfter ( BBData bbd,
bool  firstTime 
)
protected

Updates bookkeeping used for calculating register deaths.

Marks registers used at or after some BB to it's predecessor BB's.

Parameters
bbdbasic block to process.
firstTimewhether this BB is analyzer for the first time.

Definition at line 2390 of file DataDependenceGraphBuilder.cc.

2391 {
2392 BasicBlockNode& bbn = *bbd.bblock_;
2393 BasicBlock& bb = bbn.basicBlock();
2394 BasicBlockNodeSet predecessors = cfg_->predecessors(bbn);
2395 for (BasicBlockNodeSet::iterator predIter = predecessors.begin();
2396 predIter != predecessors.end(); predIter++) {
2397 BasicBlockNode* pred = *predIter;
2398 BasicBlock& predBB = pred->basicBlock();
2399 BBData& predData = *bbData_[pred];
2400 size_t size = predBB.liveRangeData_->registersUsedAfter_.size();
2403
2404 // if updated, need to be handled again.
2405 if (predBB.liveRangeData_->registersUsedAfter_.size() > size || firstTime) {
2406 if (predData.state_ != BB_QUEUED) {
2407 changeState(predData, BB_QUEUED);
2408 }
2409 }
2410 }
2411}
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const

References AssocTools::append(), BasicBlockNode::basicBlock(), BB_QUEUED, bbData_, DataDependenceGraphBuilder::BBData::bblock_, cfg_, changeState(), TTAProgram::BasicBlock::liveRangeData_, BoostGraph< GraphNode, GraphEdge >::predecessors(), LiveRangeData::registersUsedAfter_, LiveRangeData::registersUsedInOrAfter_, and DataDependenceGraphBuilder::BBData::state_.

Referenced by iterateRegisterDeaths().

Here is the call graph for this function:

◆ updateRegistersAliveAfter()

bool DataDependenceGraphBuilder::updateRegistersAliveAfter ( BBData bbd)
protected

Updates live register lists after a basic block has been processed.

Copies use and define definitions from the basic block and it's prodecessors to the after alive data structures.

Parameters
bbdBBData for bb being processed
Returns
true if the after alive data structures have been changed

Definition at line 2519 of file DataDependenceGraphBuilder.cc.

2520 {
2521 BasicBlock& bb = bbd.bblock_->basicBlock();
2522 bool changed = false;
2523
2524 // copy reg definitions that are alive
2525 for (MoveNodeUseMapSet::iterator iter =
2526 bb.liveRangeData_->regDefReaches_.begin();
2527 iter != bb.liveRangeData_->regDefReaches_.end(); iter++) {
2528
2529 TCEString reg = iter->first;
2530 std::set<MoveNodeUse>& preDefs = iter->second;
2531 // todo: clear or not?
2532 std::set<MoveNodeUse>& defAfter = bb.liveRangeData_->regDefAfter_[reg];
2533 size_t size = defAfter.size();
2534
2535 // only copy incomin dep if this has no unconditional writes
2536 if (bb.liveRangeData_->regKills_.find(reg) == bb.liveRangeData_->regKills_.end()) {
2537 for (std::set<MoveNodeUse>::iterator i = preDefs.begin();
2538 i != preDefs.end(); i++ ) {
2539 defAfter.insert(*i);
2540 }
2541 }
2542 // if size increased, the data has changed
2543 if (size < defAfter.size()) {
2544 changed = true;
2545 }
2546 }
2547 // own deps. need to do only once but now does after every.
2550 bb.liveRangeData_->regDefAfter_, false);
2551
2553 // copy uses that are alive
2554 for (MoveNodeUseMapSet::iterator iter =
2555 bb.liveRangeData_->regUseReaches_.begin(); iter != bb.liveRangeData_->regUseReaches_.end();
2556 iter++) {
2557 TCEString reg = iter->first;
2558 std::set<MoveNodeUse>& preUses = iter->second;
2559 std::set<MoveNodeUse>& useAfter = bb.liveRangeData_->regUseAfter_[reg];
2560 size_t size = useAfter.size();
2561 if (bb.liveRangeData_->regKills_.find(reg) == bb.liveRangeData_->regKills_.end()) {
2562 for (std::set<MoveNodeUse>::iterator i = preUses.begin();
2563 i != preUses.end(); i++ ) {
2564 useAfter.insert(*i);
2565 }
2566 }
2567 // if size increased, the data has changed
2568 if (size < useAfter.size()) {
2569 changed = true;
2570 }
2571 }
2572 }
2573
2574 // own deps. need to do only once but now does after every.
2577 bb.liveRangeData_->regUseAfter_, false);
2578 return changed;
2579}

References LiveRangeData::appendUseMapSets(), BasicBlockNode::basicBlock(), DataDependenceGraphBuilder::BBData::bblock_, currentDDG_, DataDependenceGraph::hasAllRegisterAntidependencies(), TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::regDefAfter_, LiveRangeData::regDefines_, LiveRangeData::regDefReaches_, LiveRangeData::regKills_, LiveRangeData::regLastUses_, LiveRangeData::regUseAfter_, and LiveRangeData::regUseReaches_.

Referenced by iterateBBs().

Here is the call graph for this function:

◆ updateRegistersUsedInOrAfter()

bool DataDependenceGraphBuilder::updateRegistersUsedInOrAfter ( BBData bbd)
protected

Updates bookkeeping about registers used in this or later BBs.

This is a helper function used by searchRegisterDeaths() method.

Parameters
bbdData about one basicblock.
Returns
whether the bookkeeping was changed, ie the predecessors of this BB need to be reprocessed.

Definition at line 2955 of file DataDependenceGraphBuilder.cc.

2956 {
2957 BasicBlock& bb = bbd.bblock_->basicBlock();
2958 size_t size = bb.liveRangeData_->registersUsedInOrAfter_.size();
2959
2960 // if definition not here, it's earlier - copy.
2961 // if definition here, not alive unless read here.
2962 for (std::set<TCEString>::iterator i = bb.liveRangeData_->registersUsedAfter_.begin();
2963 i != bb.liveRangeData_->registersUsedAfter_.end(); i++) {
2964 // if not written in this, written earlier.
2965 if (bb.liveRangeData_->regKills_.find(*i) == bb.liveRangeData_->regKills_.end()) {
2967 }
2968 }
2969
2970 // reads in this BB.liveRangeData_-> Only reads whose defining value comes/can come
2971 // outside this BB.liveRangeData_->
2972 for (MoveNodeUseMapSet::iterator i = bb.liveRangeData_->regFirstUses_.begin();
2973 i != bb.liveRangeData_->regFirstUses_.end(); i++) {
2974 bb.liveRangeData_->registersUsedInOrAfter_.insert(i->first);
2975 }
2976 if (bb.liveRangeData_->registersUsedInOrAfter_.size() > size) {
2977 return true;
2978 }
2979 return false;
2980}

References BasicBlockNode::basicBlock(), DataDependenceGraphBuilder::BBData::bblock_, TTAProgram::BasicBlock::liveRangeData_, LiveRangeData::regFirstUses_, LiveRangeData::registersUsedAfter_, LiveRangeData::registersUsedInOrAfter_, and LiveRangeData::regKills_.

Referenced by iterateRegisterDeaths().

Here is the call graph for this function:

Member Data Documentation

◆ aliasAnalyzers_

AliasAnalyzerVector DataDependenceGraphBuilder::aliasAnalyzers_
protected

◆ allParamRegs_

std::set<TCEString> DataDependenceGraphBuilder::allParamRegs_
protected

◆ bbData_

BBDataMap DataDependenceGraphBuilder::bbData_
protected

◆ blocksByState_

BBDataList DataDependenceGraphBuilder::blocksByState_[BB_STATES]
protected

◆ cfg_

ControlFlowGraph* DataDependenceGraphBuilder::cfg_
protected

◆ currentBB_

BasicBlockNode* DataDependenceGraphBuilder::currentBB_
protected

◆ currentData_

BBData* DataDependenceGraphBuilder::currentData_
protected

◆ currentDDG_

DataDependenceGraph* DataDependenceGraphBuilder::currentDDG_
protected

◆ interPassData_

InterPassData* DataDependenceGraphBuilder::interPassData_
protected

Definition at line 319 of file DataDependenceGraphBuilder.hh.

◆ mach_

const TTAMachine::Machine* DataDependenceGraphBuilder::mach_
protected

Definition at line 322 of file DataDependenceGraphBuilder.hh.

Referenced by build(), build(), and isTriggering().

◆ RA_NAME

const TCEString DataDependenceGraphBuilder::RA_NAME = "RA"
staticprotected

Internal constant for the name of the return address port

Definition at line 318 of file DataDependenceGraphBuilder.hh.

Referenced by processCall(), processDestination(), processEntryNode(), and processSource().

◆ rvIsParamReg_

bool DataDependenceGraphBuilder::rvIsParamReg_
protected

◆ specialRegisters_

SpecialRegisters DataDependenceGraphBuilder::specialRegisters_
protected

contains stack pointer, RV and parameter registers.

Definition at line 317 of file DataDependenceGraphBuilder.hh.

Referenced by build(), build(), DataDependenceGraphBuilder(), processCall(), processEntryNode(), and processReturn().


The documentation for this class was generated from the following files: