Otawa  0.10
IterativeDFA.h
Go to the documentation of this file.
1 /*
2  * $Id$
3  * IterativeDFA class interface
4  *
5  * This file is part of OTAWA
6  * Copyright (c) 2007-08, IRIT UPS.
7  *
8  * OTAWA is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * OTAWA is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with OTAWA; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 #ifndef OTAWA_UTIL_ITERATIVE_DFA_H
23 #define OTAWA_UTIL_ITERATIVE_DFA_H
24 
25 #include <elm/assert.h>
26 #include <elm/genstruct/VectorQueue.h>
27 #include <elm/util/BitVector.h>
28 #include <otawa/cfg.h>
29 
30 #ifdef OTAWA_IDFA_DEBUG
31 # define OTAWA_IDFA_TRACE(x) cerr << x << io::endl
32 # define OTAWA_IDFA_DUMP(m, s) { cerr << m << "= "; prob.dump(cerr, s); cerr << io::endl; }
33 #else
34 # define OTAWA_IDFA_TRACE(x)
35 # define OTAWA_IDFA_DUMP(m, s)
36 #endif
37 
38 namespace otawa { namespace dfa {
39 
40 // predeclaration
41 class Successor;
42 
43 // Predecessor
44 class Predecessor: public PreIterator<Predecessor, BasicBlock *> {
46  inline void look(void) {
47  while(iter && iter->kind() == Edge::CALL)
48  iter++;
49  }
50 public:
51  typedef Successor Forward;
52  inline Predecessor(BasicBlock *bb): iter(bb) {
53  look();
54  };
55  static inline BasicBlock *entry(CFG& cfg) { return cfg.entry(); }
56  inline BasicBlock *item(void) const { return iter.item()->source(); };
57  inline bool ended(void) const { return iter.ended(); };
58  inline void next(void) { iter.next(); look(); };
59 };
60 
61 
62 // Successor
63 class Successor: public PreIterator<Successor, BasicBlock *> {
65  inline void look(void) {
66  while(iter && iter->kind() == Edge::CALL)
67  iter++;
68  }
69 public:
71  inline Successor(BasicBlock *bb): iter(bb) {
72  look();
73  };
74  static inline BasicBlock *entry(CFG& cfg) { return cfg.exit(); }
75  inline BasicBlock *item(void) const { return iter.item()->target(); };
76  inline bool ended(void) const { return iter.ended(); };
77  inline void next(void) { iter.next(); look(); };
78 };
79 
80 
81 // DFAEngine class
82 template <class Problem, class Set, class Iter = Predecessor>
83 class IterativeDFA {
84  Problem& prob;
86  int cnt;
87  Set **ins, **outs, **gens, **kills;
88 public:
89  inline IterativeDFA(Problem& problem, CFG& cfg);
90  inline ~IterativeDFA(void);
91  inline void compute(void);
92  inline Set *inSet(BasicBlock *bb);
93  inline Set *outSet(BasicBlock *bb);
94  inline Set *genSet(BasicBlock *bb);
95  inline Set *killSet(BasicBlock *bb);
96 };
97 
98 
99 // IterativeDFA::IterativeDFA inline
100 template <class Problem, class Set, class Iter>
102 : prob(problem), _cfg(cfg), cnt(cfg.countBB()) {
103  ins = new Set *[cnt];
104  outs = new Set *[cnt];
105  gens = new Set *[cnt];
106  kills = new Set *[cnt];
107  for(CFG::BBIterator bb(&_cfg); bb; bb++) {
108  int idx = INDEX(bb);
109  ins[idx] = prob.empty();
110  outs[idx] = prob.empty();
111  gens[idx] = prob.gen(bb);
112  kills[idx] = prob.kill(bb);
113  }
114 }
115 
116 
117 // IterativeDFA::~IterativeDFA() inline
118 template <class Problem, class Set, class Iter>
120  for(int i = 0; i < cnt; i++) {
121  if(ins[i])
122  prob.free(ins[i]);
123  if(outs[i])
124  prob.free(outs[i]);
125  prob.free(gens[i]);
126  prob.free(kills[i]);
127  }
128  delete [] ins;
129  delete [] outs;
130  delete [] gens;
131  delete [] kills;
132 }
133 
134 
135 // IterativeDFA::inSet() inline
136 template <class Problem, class Set, class Iter>
138  return ins[INDEX(bb)];
139 }
140 
141 
142 // IterativeDFA::outSet() inline
143 template <class Problem, class Set, class Iter>
145  return outs[INDEX(bb)];
146 }
147 
148 
149 // IterativeDFA::genSet() inline
150 template <class Problem, class Set, class Iter>
152  return gens[INDEX(bb)];
153 }
154 
155 
156 // IterativeDFA::killSet() inline
157 template <class Problem, class Set, class Iter>
159  return kills[INDEX(bb)];
160 }
161 
162 
163 // IterativeDFA::compute() inline
164 template <class Problem, class Set, class Iter>
166 
167  // initialization
169  BitVector present(_cfg.countBB());
170  Set *comp = prob.empty(), *ex;
171  for(CFG::BBIterator bb(&_cfg); bb; bb++) {
172  OTAWA_IDFA_TRACE("DFA: push BB" << bb->number());
173  todo.put(bb);
174  present.set(bb->number());
175  }
176 
177  // perform until no change
178  while(todo) {
179  BasicBlock *bb = todo.get();
180  int idx = bb->number();
181  ASSERT(idx >= 0);
182  present.clear(idx);
183  OTAWA_IDFA_TRACE("DFA: processing BB" << idx);
184 
185  // IN = union OUT of predecessors
186  prob.reset(ins[idx]);
187  for(Iter pred(bb); pred; pred++) {
188  BasicBlock *bb_pred = pred;
189  int pred_idx = bb_pred->number();
190  ASSERT(pred_idx >= 0);
191  prob.merge(ins[idx], outs[pred_idx]);
192  }
193 
194  // OUT = IN \ KILL U GEN
195  prob.set(comp, ins[idx]);
196  OTAWA_IDFA_DUMP("IN", comp);
197  prob.diff(comp, kills[idx]);
198  OTAWA_IDFA_DUMP("KILL", kills[idx]);
199  prob.add(comp, gens[idx]);
200  OTAWA_IDFA_DUMP("GEN", gens[idx]);
201  OTAWA_IDFA_DUMP("OUT", comp);
202 
203  // Any modification ?
204  if(!prob.equals(comp, outs[idx])) {
205 
206  // record new out
207  ex = outs[idx];
208  outs[idx] = comp;
209  comp = ex;
210 
211  // add successors
212  for(typename Iter::Forward next(bb); next; next++)
213  if(!present.bit(next->number())) {
214  OTAWA_IDFA_TRACE("DFA: push BB" << next->number());
215  todo.put(next);
216  present.set(next->number());
217  }
218  }
219  prob.reset(comp);
220  }
221 
222  // cleanup
223  prob.free(comp);
224 }
225 
226 } } // otawa::dfa
227 
228 #endif // OTAWA_UTIL_ITERATIVE_DFA_H
Definition: CFG.h:48
#define OTAWA_IDFA_DUMP(m, s)
Definition: IterativeDFA.h:35
This iterator is used to traverse forward a CFG in an iterative DFA analysis.
Definition: IterativeDFA.h:44
Kind of an edge matching a sub-program call.
Definition: Edge.h:40
Set * genSet(BasicBlock *bb)
Get the GEN(BB) set.
Definition: IterativeDFA.h:151
Problem & prob
Definition: IterativeDFA.h:84
#define OTAWA_IDFA_TRACE(x)
Definition: IterativeDFA.h:34
BasicBlock * entry(void)
Get the entry basic block of the CFG.
Definition: CFG.h:63
dtd::Element bb(dtd::make("bb", _BB).attr(id).attr(address).attr(size))
Control Flow Graph representation.
Definition: CFG.h:42
int cnt
Definition: IterativeDFA.h:86
CFG & _cfg
Definition: IterativeDFA.h:85
Set * inSet(BasicBlock *bb)
Get the IN(BB) set.
Definition: IterativeDFA.h:137
BasicBlock * exit(void)
Get the exit basic block of the CFG.
Definition: CFG.h:65
void look(void)
Definition: IterativeDFA.h:65
bool ended(void) const
Definition: IterativeDFA.h:76
static BasicBlock * entry(CFG &cfg)
Definition: IterativeDFA.h:74
IterativeDFA(Problem &problem, CFG &cfg)
Definition: IterativeDFA.h:101
BasicBlock * item(void) const
Definition: IterativeDFA.h:75
Set * outSet(BasicBlock *bb)
Get the OUT(BB) set.
Definition: IterativeDFA.h:144
Definition: BasicBlock.h:165
void put(const T &value)
void compute(void)
Perform the iterative DFA analysis.
Definition: IterativeDFA.h:165
int number(void) const
Get the number hooked on this basic block, that is, value of ID_Index property.
Definition: BasicBlock.h:146
BasicBlock::InIterator iter
Definition: IterativeDFA.h:45
Set * killSet(BasicBlock *bb)
Get the KILL(BB) set.
Definition: IterativeDFA.h:158
This iterator is used to traverse backward a CFG in an iterative DFA analysis.
Definition: IterativeDFA.h:63
BasicBlock::OutIterator iter
Definition: IterativeDFA.h:64
Successor(BasicBlock *bb)
Definition: IterativeDFA.h:71
Predecessor(BasicBlock *bb)
Definition: IterativeDFA.h:52
Set ** kills
Definition: IterativeDFA.h:87
Definition: BasicBlock.h:160
bool ended(void) const
Definition: IterativeDFA.h:57
Set ** outs
Definition: IterativeDFA.h:87
Identifier< int > INDEX
Identifier used for internal use.
static BasicBlock * entry(CFG &cfg)
Definition: IterativeDFA.h:55
dtd::Element cfg(dtd::make("cfg", _CFG).attr(id).content((entry,*bb, exit,*edge)))
Set ** gens
Definition: IterativeDFA.h:87
This is the minimal definition of a basic block.
Definition: BasicBlock.h:43
void next(void)
Definition: IterativeDFA.h:77
void next(void)
Definition: IterativeDFA.h:58
Predecessor Forward
Definition: IterativeDFA.h:70
void look(void)
Definition: IterativeDFA.h:46
Successor Forward
Definition: IterativeDFA.h:51
~IterativeDFA(void)
Definition: IterativeDFA.h:119
Set ** ins
Definition: IterativeDFA.h:87
BasicBlock * item(void) const
Definition: IterativeDFA.h:56
This class provides a generic facility to implement iterative Data Flow Analysis (DFA) as presented i...
Definition: IterativeDFA.h:83