OpenASIP  2.0
MemoryAliasAnalyzer.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * @file MemoryAliasAnalyzer.cc
26  *
27  * Implementation of Memory Alias Analyzer interface
28  *
29  * @author Heikki Kultala 2009 (heikki.kultala-no.spam-tut.fi)
30  * @author Heikki Kultala 2010 (heikki.kultala-no.spam-tut.fi)
31  * @note rating: red
32  */
33 
34 #include "MemoryAliasAnalyzer.hh"
35 #include "MoveNode.hh"
36 #include "ProgramOperation.hh"
37 #include "TCEString.hh"
38 #include "Operand.hh"
39 #include "OperationDAG.hh"
40 #include "OperationNode.hh"
41 #include "TerminalNode.hh"
42 #include "MoveNodeSet.hh"
43 #include "Operation.hh"
44 #include "Move.hh"
45 #include "Terminal.hh"
46 #include "DataDependenceGraph.hh"
47 
48 /**
49  * Compares two indeces (memory addresses or part of memory address).
50  * Checks memory operand size and return unknown for partial alias.
51  *
52  * This methods takes care of checking memory access size and handling
53  * partial aliasing (returning unknown for those)
54  *
55  * @param index1 first index to compare
56  * @param index2 second index to compare
57  * @param mn1 first node
58  * @param mn2 second node
59  * @return true if alias, false if not alias, unknown for partial alias.
60  */
63  int index1, int index2, const ProgramOperation& pop1,
64  const ProgramOperation& pop2) {
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 }
95 /**
96  * Returns the size of memory operation memory access in mau's.
97  * if unknown, returns 0.
98  */
99 unsigned int
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 }
136 
137 /**
138  * Gets the direct address-writing move of a ProgramOperation which is a memory
139  * operation.
140  *
141  * If none found, return null
142  *
143  * @param po programOperation whose address write move is being searched.
144  * @return MoveNode which writes address to a mem operation or NULL.
145  */
146 const MoveNode*
148  const ProgramOperation& po) {
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 }
172 
173 
176  const ProgramOperation& po) {
177 
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 }
272 
273 const MoveNode* MemoryAliasAnalyzer::findIncrement(const MoveNode& mn, long& increment) {
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 }
320 
322  DataDependenceGraph& ddg, const MoveNode &mn, long& loopIncrement) {
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 }
388 
389 const MoveNode* MemoryAliasAnalyzer::detectConstantScale(const MoveNode& mn, int &shiftAmount) {
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 }
Operand
Definition: Operand.hh:52
OperationDAGEdge::dstOperand
int dstOperand() const
Definition: OperationDAGEdge.cc:54
ProgramOperation::operation
const Operation & operation() const
Definition: ProgramOperation.cc:590
SimValue::intValue
int intValue() const
Definition: SimValue.cc:895
BoostGraph::predecessors
virtual NodeSet predecessors(const Node &node, bool ignoreBackEdges=false, bool ignoreForwardEdges=false) const
MemoryAliasAnalyzer::ALIAS_UNKNOWN
@ ALIAS_UNKNOWN
Definition: MemoryAliasAnalyzer.hh:54
BoostGraph::tailNode
virtual Node & tailNode(const Edge &edge) const
MemoryAliasAnalyzer::mausOfOperation
unsigned int mausOfOperation(const Operation &op)
Definition: MemoryAliasAnalyzer.cc:100
MemoryAliasAnalyzer::ALIAS_FALSE
@ ALIAS_FALSE
Definition: MemoryAliasAnalyzer.hh:50
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::NOT_FOUND
@ NOT_FOUND
Definition: MemoryAliasAnalyzer.hh:85
BoostGraph< OperationDAGNode, OperationDAGEdge >::NodeSet
std::set< OperationDAGNode *, typename OperationDAGNode ::Comparator > NodeSet
Definition: BoostGraph.hh:86
TerminalNode
Definition: TerminalNode.hh:47
Operation::numberOfInputs
virtual int numberOfInputs() const
Definition: Operation.cc:192
DataDependenceGraph.hh
ProgramOperation
Definition: ProgramOperation.hh:70
MoveNode
Definition: MoveNode.hh:65
MoveNode::isSourceConstant
bool isSourceConstant() const
Definition: MoveNode.cc:238
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::clear
void clear()
Definition: MemoryAliasAnalyzer.hh:92
OperationNode::referencedOperation
Operation & referencedOperation() const
Definition: OperationNode.cc:70
Terminal.hh
OperationNode
Definition: OperationNode.hh:47
Operation::name
virtual TCEString name() const
Definition: Operation.cc:93
OperationDAGEdge
Definition: OperationDAGEdge.hh:38
DataDependenceGraph::onlyRegisterRawSource
MoveNode * onlyRegisterRawSource(const MoveNode &mn, int allowGuardEdges=2, int backEdges=0) const
Definition: DataDependenceGraph.cc:4083
MemoryAliasAnalyzer::detectConstantScale
static const MoveNode * detectConstantScale(const MoveNode &mn, int &shiftAmount)
Definition: MemoryAliasAnalyzer.cc:389
MemoryAliasAnalyzer::findTwoPartAddressOperands
static TwoPartAddressOperandDetection findTwoPartAddressOperands(const ProgramOperation &po)
Definition: MemoryAliasAnalyzer.cc:175
OperationDAG::endNodes
const OperationDAG::NodeSet & endNodes() const
Definition: OperationDAG.cc:137
TCEString.hh
MoveNode::sourceOperation
ProgramOperation & sourceOperation() const
Definition: MoveNode.cc:453
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::offsetOperation
OffsetOperation offsetOperation
Definition: MemoryAliasAnalyzer.hh:86
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::operand2
int operand2
Definition: MemoryAliasAnalyzer.hh:88
MemoryAliasAnalyzer::AliasingResult
AliasingResult
Definition: MemoryAliasAnalyzer.hh:50
MemoryAliasAnalyzer::ALIAS_TRUE
@ ALIAS_TRUE
Definition: MemoryAliasAnalyzer.hh:53
InvalidData
Definition: Exception.hh:149
OperationDAGNode
Definition: OperationDAGNode.hh:45
MoveNodeSet::at
MoveNode & at(int index)
BoostGraph::inEdge
virtual Edge & inEdge(const Node &node, const int index) const
OperationDAG.hh
OperationDAG
Definition: OperationDAG.hh:43
__func__
#define __func__
Definition: Application.hh:67
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
Operation.hh
MoveNode::isSourceOperation
bool isSourceOperation() const
Definition: MoveNode.cc:168
TTAProgram::Terminal::value
virtual SimValue value() const
Definition: Terminal.cc:178
MemoryAliasAnalyzer::searchLoopIndexBasedIncrement
static const MoveNode * searchLoopIndexBasedIncrement(DataDependenceGraph &ddg, const MoveNode &mn, long &loopIncrement)
Definition: MemoryAliasAnalyzer.cc:321
MemoryAliasAnalyzer::addressOperandMove
static const MoveNode * addressOperandMove(const ProgramOperation &po)
Definition: MemoryAliasAnalyzer.cc:147
BoostGraph::inDegree
virtual int inDegree(const Node &node) const
MoveNodeSet
Definition: MoveNodeSet.hh:41
Operation
Definition: Operation.hh:59
ProgramOperation.hh
Operand.hh
MoveNodeSet::count
int count() const
Operation::input
virtual Operand & input(int index) const
Definition: Operation.cc:503
MoveNode::isSourceVariable
bool isSourceVariable() const
Definition: MoveNode.cc:196
Operation::usesMemory
virtual bool usesMemory() const
Definition: Operation.cc:232
MoveNode::move
TTAProgram::Move & move()
Operation::dagCount
virtual int dagCount() const
Definition: Operation.cc:134
MemoryAliasAnalyzer::findIncrement
static const MoveNode * findIncrement(const MoveNode &mn, long &increment)
Definition: MemoryAliasAnalyzer.cc:273
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::SUB
@ SUB
Definition: MemoryAliasAnalyzer.hh:85
MemoryAliasAnalyzer::compareIndeces
AliasingResult compareIndeces(int index1, int index2, const ProgramOperation &pop1, const ProgramOperation &pop2)
Definition: MemoryAliasAnalyzer.cc:62
MoveNodeSet.hh
DataDependenceGraph
Definition: DataDependenceGraph.hh:67
TerminalNode.hh
ProgramOperation::inputNode
MoveNodeSet & inputNode(int in) const
Definition: ProgramOperation.cc:513
Operand::memoryUnits
virtual int memoryUnits() const
Definition: Operand.cc:341
MemoryAliasAnalyzer.hh
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::ADD
@ ADD
Definition: MemoryAliasAnalyzer.hh:85
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
Operand::isAddress
virtual bool isAddress() const
Definition: Operand.cc:328
OperationNode.hh
MemoryAliasAnalyzer::TwoPartAddressOperandDetection
Definition: MemoryAliasAnalyzer.hh:84
Move.hh
TTAProgram::Terminal::isImmediate
virtual bool isImmediate() const
Definition: Terminal.cc:63
MoveNode.hh
Operation::dag
virtual OperationDAG & dag(int index) const
Definition: Operation.cc:148
MemoryAliasAnalyzer::TwoPartAddressOperandDetection::operand1
int operand1
Definition: MemoryAliasAnalyzer.hh:87
TerminalNode::operandIndex
virtual int operandIndex() const
Definition: TerminalNode.cc:60