OpenASIP 2.2
Loading...
Searching...
No Matches
Classes | Public Types | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Private Member Functions | List of all members
MemoryAliasAnalyzer Class Referenceabstract

#include <MemoryAliasAnalyzer.hh>

Inheritance diagram for MemoryAliasAnalyzer:
Inheritance graph
Collaboration diagram for MemoryAliasAnalyzer:
Collaboration graph

Classes

struct  TwoPartAddressOperandDetection
 

Public Types

enum  AliasingResult { ALIAS_FALSE = 0 , ALIAS_TRUE = 1 , ALIAS_UNKNOWN = 2 , ALIAS_PARTIAL = 3 }
 

Public Member Functions

virtual void initProcedure (TTAProgram::Procedure &)
 
virtual AliasingResult analyze (DataDependenceGraph &ddg, const ProgramOperation &pop1, const ProgramOperation &pop2, MoveNodeUse::BBRelation bbInfo)=0
 
virtual bool isAddressTraceable (DataDependenceGraph &ddg, const ProgramOperation &pop)=0
 
virtual ~MemoryAliasAnalyzer ()
 

Protected Member Functions

AliasingResult compareIndeces (int index1, int index2, const ProgramOperation &pop1, const ProgramOperation &pop2)
 

Static Protected Member Functions

static const MoveNodeaddressOperandMove (const ProgramOperation &po)
 
static TwoPartAddressOperandDetection findTwoPartAddressOperands (const ProgramOperation &po)
 
static const MoveNodesearchLoopIndexBasedIncrement (DataDependenceGraph &ddg, const MoveNode &mn, long &loopIncrement)
 
static const MoveNodefindIncrement (const MoveNode &mn, long &increment)
 
static const MoveNodedetectConstantScale (const MoveNode &mn, int &shiftAmount)
 

Private Member Functions

unsigned int mausOfOperation (const Operation &op)
 

Detailed Description

Definition at line 47 of file MemoryAliasAnalyzer.hh.

Member Enumeration Documentation

◆ AliasingResult

Enumerator
ALIAS_FALSE 
ALIAS_TRUE 
ALIAS_UNKNOWN 
ALIAS_PARTIAL 

Definition at line 50 of file MemoryAliasAnalyzer.hh.

50 { ALIAS_FALSE = 0,
51 // Only Use ALIAS_TRUE if they really fully alias.
52 // It's used for transitivity optimizations.
53 ALIAS_TRUE = 1,
54 ALIAS_UNKNOWN = 2,
55 ALIAS_PARTIAL = 3};

Constructor & Destructor Documentation

◆ ~MemoryAliasAnalyzer()

virtual MemoryAliasAnalyzer::~MemoryAliasAnalyzer ( )
inlinevirtual

Definition at line 75 of file MemoryAliasAnalyzer.hh.

75{}

Member Function Documentation

◆ addressOperandMove()

const MoveNode * MemoryAliasAnalyzer::addressOperandMove ( const ProgramOperation po)
staticprotected

Gets the direct address-writing move of a ProgramOperation which is a memory operation.

If none found, return null

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

Definition at line 147 of file MemoryAliasAnalyzer.cc.

148 {
149 const Operation& op = po.operation();
150
151 // no mem address if does not use memory
152 if (!op.usesMemory()) {
153 return NULL;
154 }
155
156 // loops thru all inputs, checks if it is an address.
157 // the index for op.input() starts from 0
158 for (int i = 0, inputCount = op.numberOfInputs() ; i < inputCount; i++) {
159 Operand& operand = op.input(i);
160 if (operand.isAddress()) {
161 // the index for po.inpuNode starts from 0 , so add +1
162 MoveNodeSet& mns = po.inputNode(i+1);
163 if (mns.count() != 1) {
164 return NULL;
165 } else {
166 return &mns.at(0);
167 }
168 }
169 }
170 return NULL;
171}
int count() const
MoveNode & at(int index)
virtual bool isAddress() const
Definition Operand.cc:328
virtual bool usesMemory() const
Definition Operation.cc:232
virtual Operand & input(int index) const
Definition Operation.cc:503
virtual int numberOfInputs() const
Definition Operation.cc:192
const Operation & operation() const
MoveNodeSet & inputNode(int in) const

References MoveNodeSet::at(), MoveNodeSet::count(), Operation::input(), ProgramOperation::inputNode(), Operand::isAddress(), Operation::numberOfInputs(), ProgramOperation::operation(), and Operation::usesMemory().

Referenced by PRegionAliasAnalyzer::analyze(), OffsetAliasAnalyzer::analyze(), ConstantAliasAnalyzer::getConstantAddress(), StackAliasAnalyzer::getStackOffset(), and OffsetAliasAnalyzer::isAddressTraceable().

Here is the call graph for this function:

◆ analyze()

virtual AliasingResult MemoryAliasAnalyzer::analyze ( DataDependenceGraph ddg,
const ProgramOperation pop1,
const ProgramOperation pop2,
MoveNodeUse::BBRelation  bbInfo 
)
pure virtual

◆ compareIndeces()

MemoryAliasAnalyzer::AliasingResult MemoryAliasAnalyzer::compareIndeces ( int  index1,
int  index2,
const ProgramOperation pop1,
const ProgramOperation pop2 
)
protected

Compares two indeces (memory addresses or part of memory address). Checks memory operand size and return unknown for partial alias.

This methods takes care of checking memory access size and handling partial aliasing (returning unknown for those)

Parameters
index1first index to compare
index2second index to compare
mn1first node
mn2second node
Returns
true if alias, false if not alias, unknown for partial alias.

Definition at line 62 of file MemoryAliasAnalyzer.cc.

64 {
65 const Operation& op1 = pop1.operation();
66 const Operation& op2 = pop2.operation();
67
68 int maus1 = mausOfOperation(op1);
69 int maus2 = mausOfOperation(op2);
70
71 // unknown op? don't know how much memory it touches.
72 if (maus1 == 0 || maus2 == 0) {
73 return ALIAS_UNKNOWN;
74 }
75
76 // if addresses are the same.
77 if (index1 == index2) {
78 // partial?
79 if (maus1 != maus2) {
80 return ALIAS_UNKNOWN;
81 } else {
82 return ALIAS_TRUE;
83 }
84 }
85
86 int maus = std::max(maus1, maus2);
87
88 // partial alias or not?
89 if ((index1 & (~(maus-1))) == (index2 & (~(maus-1)))) {
90 return ALIAS_UNKNOWN;
91 } else {
92 return ALIAS_FALSE;
93 }
94}
unsigned int mausOfOperation(const Operation &op)

References ALIAS_FALSE, ALIAS_TRUE, ALIAS_UNKNOWN, mausOfOperation(), and ProgramOperation::operation().

Referenced by ConstantAliasAnalyzer::analyze(), StackAliasAnalyzer::analyze(), and OffsetAliasAnalyzer::analyze().

Here is the call graph for this function:

◆ detectConstantScale()

const MoveNode * MemoryAliasAnalyzer::detectConstantScale ( const MoveNode mn,
int &  shiftAmount 
)
staticprotected

Definition at line 389 of file MemoryAliasAnalyzer.cc.

389 {
390 if (!mn.isSourceOperation()) {
391 return NULL;
392 }
394 if (po.operation().name() != "SHL") {
395 return NULL;
396 }
397 MoveNodeSet& input1Set = po.inputNode(1);
398 MoveNodeSet& input2Set = po.inputNode(2);
399 if (input1Set.count() != 1 || input2Set.count() != 1) {
400 return NULL;
401 }
402 const MoveNode& input1 = input1Set.at(0);
403 const MoveNode& input2 = input2Set.at(0);
404 if (!input1.isSourceVariable() ||
405 !input2.isSourceConstant()) {
406 return NULL;
407 }
408 shiftAmount = input2.move().source().value().intValue();
409 return &input1;
410}
bool isSourceVariable() const
Definition MoveNode.cc:196
ProgramOperation & sourceOperation() const
Definition MoveNode.cc:453
TTAProgram::Move & move()
bool isSourceOperation() const
Definition MoveNode.cc:168
bool isSourceConstant() const
Definition MoveNode.cc:238
virtual TCEString name() const
Definition Operation.cc:93
int intValue() const
Definition SimValue.cc:895
Terminal & source() const
Definition Move.cc:302
virtual SimValue value() const
Definition Terminal.cc:178

References MoveNodeSet::at(), MoveNodeSet::count(), ProgramOperation::inputNode(), SimValue::intValue(), MoveNode::isSourceConstant(), MoveNode::isSourceOperation(), MoveNode::isSourceVariable(), MoveNode::move(), Operation::name(), ProgramOperation::operation(), TTAProgram::Move::source(), MoveNode::sourceOperation(), and TTAProgram::Terminal::value().

Referenced by searchLoopIndexBasedIncrement().

Here is the call graph for this function:

◆ findIncrement()

const MoveNode * MemoryAliasAnalyzer::findIncrement ( const MoveNode mn,
long &  increment 
)
staticprotected

Definition at line 273 of file MemoryAliasAnalyzer.cc.

273 {
274 int myInc = 0;
275 if (!mn.isSourceOperation()) {
276 return NULL;
277 }
278
280 bool isSub = po.operation().name() == "SUB";
281 bool isAdd = po.operation().name() == "ADD";
282 if (!isSub && !isAdd) {
283 return NULL;
284 }
285
286 // is add or sub
287 MoveNodeSet& input1Set = po.inputNode(1);
288 MoveNodeSet& input2Set = po.inputNode(2);
289 if (input1Set.count() != 1 || input2Set.count() != 1) {
290 return NULL;
291 }
292 MoveNode& input1 = input1Set.at(0);
293 MoveNode& input2 = input2Set.at(0);
294 MoveNode *immMove = NULL;
295 MoveNode* varMove = NULL;
296 if (input1.move().source().isGPR() &&
297 input2.move().source().isImmediate()) {
298 immMove = &input2;
299 varMove = &input1;
300 } else if (input2.move().source().isGPR() &&
301 input1.move().source().isImmediate()) {
302 // no sub by variable
303 if (isSub) {
304 return NULL;
305 }
306 immMove = &input1;
307 varMove = &input2;
308 } else { // not yet supported.
309 return NULL;
310 }
311
312 myInc = immMove->move().source().value().intValue();
313 if (isSub) {
314 increment -= myInc;
315 } else {
316 increment += myInc;
317 }
318 return varMove;
319}
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isImmediate() const
Definition Terminal.cc:63

References MoveNodeSet::at(), MoveNodeSet::count(), ProgramOperation::inputNode(), SimValue::intValue(), TTAProgram::Terminal::isGPR(), TTAProgram::Terminal::isImmediate(), MoveNode::isSourceOperation(), MoveNode::move(), Operation::name(), ProgramOperation::operation(), TTAProgram::Move::source(), MoveNode::sourceOperation(), and TTAProgram::Terminal::value().

Referenced by OffsetAliasAnalyzer::analyzeLoopPtrIncrease(), ConstantAliasAnalyzer::getConstantAddress(), StackAliasAnalyzer::getStackOffset(), and searchLoopIndexBasedIncrement().

Here is the call graph for this function:

◆ findTwoPartAddressOperands()

MemoryAliasAnalyzer::TwoPartAddressOperandDetection MemoryAliasAnalyzer::findTwoPartAddressOperands ( const ProgramOperation po)
staticprotected

Definition at line 175 of file MemoryAliasAnalyzer.cc.

176 {
177
178 TwoPartAddressOperandDetection result;
179 // std::set<int> operandIndeces;
180
181 const Operation& op = po.operation();
182 // TODO: assumes only one operation of dag uses memory.
183 // like base + offset stores/loads.
184 for (int i = 0; i < op.dagCount(); i++) {
185 OperationDAG& oDag = op.dag(i);
186 OperationDAG::NodeSet tailNodes = oDag.endNodes();
187 for (OperationDAG::NodeSet::iterator j = tailNodes.begin();
188 j != tailNodes.end(); j++) {
189 OperationDAGNode* n = *j;
190 OperationNode* on = dynamic_cast<OperationNode*>(n);
191 if (on == NULL) {
192 continue;
193 }
194 Operation& tailOp = on->referencedOperation();
195 if (!tailOp.usesMemory()) {
196 continue;
197 }
198 int addrOperandNum = 0;
199 for (int k = 0, inputCount = tailOp.numberOfInputs() ;
200 k < inputCount; k++) {
201 Operand& operand = tailOp.input(k);
202 if (operand.isAddress()) {
203 addrOperandNum = k+1;
204 }
205 }
206 if (addrOperandNum == 0) {
207 continue;
208 }
209
210 // now we know the address operand of the mem op in dag.
211
212 OperationDAGNode* addressSource = NULL;
213 for (int k = 0; k < oDag.inDegree(*n); k++) {
214 OperationDAGEdge& e = oDag.inEdge(*n,k);
215 if (e.dstOperand() == addrOperandNum) {
216 addressSource = &oDag.tailNode(e);
217 }
218 }
219 if (addressSource == NULL) {
220 continue;
221 }
222
223 OperationNode* addrSrcOn = dynamic_cast<OperationNode*>(
224 addressSource);
225 if (addrSrcOn == NULL) {
226 continue;
227 }
228 Operation& addrOp = addrSrcOn->referencedOperation();
229 if (addrOp.name() == "add" ||
230 addrOp.name() == "ADD") {
231 result.offsetOperation =
233 } else {
234 if (addrOp.name() == "sub" ||
235 addrOp.name() == "SUB") {
236 result.offsetOperation =
238 } else {
239 result.offsetOperation =
241 continue;
242 }
243 }
244 OperationDAG::NodeSet addrInputs = oDag.predecessors(
245 *addressSource);
246
247 if (addrInputs.size() != 2) {
248 result.clear();
249 continue;
250 }
251 for (OperationDAG::NodeSet::iterator k = addrInputs.begin();
252 k != addrInputs.end(); k++) {
253 TerminalNode* tn = dynamic_cast<TerminalNode*>(*k);
254 if (tn == NULL) {
255 break;
256 }
257 if (result.operand1 == 0) {
258 result.operand1 = tn->operandIndex();
259 } else {
260 result.operand2 = tn->operandIndex();
261 }
262 }
263 if (result.operand2 != 0) {
264 return result;
265 } else {
266 result.clear();
267 }
268 }
269 }
270 return result;
271}
virtual Edge & inEdge(const Node &node, const int index) const
virtual int inDegree(const Node &node) const
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
virtual Node & tailNode(const Edge &edge) const
std::set< GraphNode *, typename GraphNode::Comparator > NodeSet
Definition Graph.hh:53
const OperationDAG::NodeSet & endNodes() const
Operation & referencedOperation() const
virtual OperationDAG & dag(int index) const
Definition Operation.cc:148
virtual int dagCount() const
Definition Operation.cc:134
virtual int operandIndex() const

References MemoryAliasAnalyzer::TwoPartAddressOperandDetection::ADD, MemoryAliasAnalyzer::TwoPartAddressOperandDetection::clear(), Operation::dag(), Operation::dagCount(), OperationDAGEdge::dstOperand(), OperationDAG::endNodes(), BoostGraph< GraphNode, GraphEdge >::inDegree(), BoostGraph< GraphNode, GraphEdge >::inEdge(), Operation::input(), Operand::isAddress(), Operation::name(), MemoryAliasAnalyzer::TwoPartAddressOperandDetection::NOT_FOUND, Operation::numberOfInputs(), MemoryAliasAnalyzer::TwoPartAddressOperandDetection::offsetOperation, MemoryAliasAnalyzer::TwoPartAddressOperandDetection::operand1, MemoryAliasAnalyzer::TwoPartAddressOperandDetection::operand2, TerminalNode::operandIndex(), ProgramOperation::operation(), BoostGraph< GraphNode, GraphEdge >::predecessors(), OperationNode::referencedOperation(), MemoryAliasAnalyzer::TwoPartAddressOperandDetection::SUB, BoostGraph< GraphNode, GraphEdge >::tailNode(), and Operation::usesMemory().

Referenced by OffsetAliasAnalyzer::analyze(), StackAliasAnalyzer::getStackOffset(), and OffsetAliasAnalyzer::isAddressTraceable().

Here is the call graph for this function:

◆ initProcedure()

virtual void MemoryAliasAnalyzer::initProcedure ( TTAProgram::Procedure )
inlinevirtual

Definition at line 57 of file MemoryAliasAnalyzer.hh.

57{}

◆ isAddressTraceable()

virtual bool MemoryAliasAnalyzer::isAddressTraceable ( DataDependenceGraph ddg,
const ProgramOperation pop 
)
pure virtual

Checks whether the analyzer knows anything about the address.

ie. if it can return true or false to some query concerning this address.

Returns
true if analyzer can know something about the address.

Implemented in ConstantAliasAnalyzer, GlobalVsStackAA, LLVMAliasAnalyzer, OffsetAliasAnalyzer, PRegionAliasAnalyzer, StackAliasAnalyzer, and FalseAliasAnalyzer.

◆ mausOfOperation()

unsigned int MemoryAliasAnalyzer::mausOfOperation ( const Operation op)
private

Returns the size of memory operation memory access in mau's. if unknown, returns 0.

Definition at line 100 of file MemoryAliasAnalyzer.cc.

100 {
101
102 // no mem address if does not use memory
103 if (!op.usesMemory()) {
104 throw InvalidData(__FILE__,__LINE__,__func__, "does not use mem!");
105 }
106
107 // loops thru all inputs, checks if it is address.
108 // the index for op.input() starts from 0
109 for (int i = 0; i < op.numberOfInputs(); i++) {
110 Operand& operand = op.input(i);
111 if (operand.isAddress()) {
112 return operand.memoryUnits();
113 }
114 }
115
116 // TODO: assumes only operation of dag uses memory.
117 // like base + offset stores/loads.
118 for (int i = 0; i < op.dagCount(); i++) {
119 OperationDAG& oDag = op.dag(i);
120 OperationDAG::NodeSet tailNodes = oDag.endNodes();
121 for (OperationDAG::NodeSet::iterator j = tailNodes.begin();
122 j != tailNodes.end(); j++) {
123 OperationDAGNode* n = *j;
124 OperationNode* on = dynamic_cast<OperationNode*>(n);
125 if (on != NULL) {
126 Operation& tailOp = on->referencedOperation();
127 if (tailOp.usesMemory()) {
128 return mausOfOperation(tailOp);
129 }
130 }
131 }
132 }
133 // unknown or no specified
134 return 0;
135}
#define __func__
virtual int memoryUnits() const
Definition Operand.cc:341

References __func__, Operation::dag(), Operation::dagCount(), OperationDAG::endNodes(), Operation::input(), Operand::isAddress(), mausOfOperation(), Operand::memoryUnits(), Operation::numberOfInputs(), OperationNode::referencedOperation(), and Operation::usesMemory().

Referenced by compareIndeces(), and mausOfOperation().

Here is the call graph for this function:

◆ searchLoopIndexBasedIncrement()

const MoveNode * MemoryAliasAnalyzer::searchLoopIndexBasedIncrement ( DataDependenceGraph ddg,
const MoveNode mn,
long &  loopIncrement 
)
staticprotected

Definition at line 321 of file MemoryAliasAnalyzer.cc.

322 {
323
325 if (po.operation().name() != "ADD") return NULL;
326
327 MoveNodeSet& input1Set = po.inputNode(1);
328 MoveNodeSet& input2Set = po.inputNode(2);
329 if (input1Set.count() != 1 || input2Set.count() != 1) {
330 return NULL;
331 }
332 const MoveNode& input1 = input1Set.at(0);
333 const MoveNode& input2 = input2Set.at(0);
334
335 if (!input1.isSourceVariable() || !input2.isSourceVariable()) {
336 return NULL;
337 }
338
339 const MoveNode* prevSrc2 = ddg.onlyRegisterRawSource(input2,2,2);
340 const MoveNode* loopSrc2 = ddg.onlyRegisterRawSource(input2,2,1);
341 if (prevSrc2 == NULL) {
342 return NULL;
343 }
344
345 int loopMul = 1;
346 if (!loopSrc2) {
347 int shiftAmount;
348 const MoveNode* loopIndex;
349 if (( loopIndex = detectConstantScale(*prevSrc2, shiftAmount))) {
350 prevSrc2 = ddg.onlyRegisterRawSource(*loopIndex,2,2);
351 if (prevSrc2 == NULL) {
352 return NULL;
353 }
354 loopMul <<= shiftAmount;
355 if (!(loopSrc2 = ddg.onlyRegisterRawSource(*loopIndex,2,1))) {
356 return NULL;
357 }
358 } else {
359 return NULL;
360 }
361 }
362
363 while (prevSrc2->isSourceVariable()) {
364 prevSrc2 = ddg.onlyRegisterRawSource(*prevSrc2);
365 if (prevSrc2 == NULL) {
366 return NULL;
367 }
368 }
369
370 // TODO: track over multiple copies
371 if (!prevSrc2->isSourceConstant()) {
372 return NULL;
373 }
374 int counterInit = prevSrc2->move().source().value().intValue();
375 if (counterInit != 0) {
376 return NULL;
377 }
378
379 long increment = 0;
380 const MoveNode* baseOfInc = findIncrement(*loopSrc2, increment);
381 if (!baseOfInc) {
382 return NULL;
383 }
384 loopIncrement = increment * loopMul;
385 // TODO: should check that the loop update really goes over the loop
386 return &input1;
387}
MoveNode * onlyRegisterRawSource(const MoveNode &mn, int allowGuardEdges=2, int backEdges=0) const
static const MoveNode * findIncrement(const MoveNode &mn, long &increment)
static const MoveNode * detectConstantScale(const MoveNode &mn, int &shiftAmount)

References MoveNodeSet::at(), MoveNodeSet::count(), detectConstantScale(), findIncrement(), ProgramOperation::inputNode(), SimValue::intValue(), MoveNode::isSourceConstant(), MoveNode::isSourceVariable(), MoveNode::move(), Operation::name(), DataDependenceGraph::onlyRegisterRawSource(), ProgramOperation::operation(), TTAProgram::Move::source(), MoveNode::sourceOperation(), and TTAProgram::Terminal::value().

Referenced by ConstantAliasAnalyzer::getConstantAddress().

Here is the call graph for this function:

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