1 package Analysis.Loops;
5 public class LoopInvariant {
6 public LoopInvariant(TypeUtil typeutil) {
7 this.typeutil=typeutil;
11 Hashtable<Loops, Set<FlatNode>> table;
12 Set<FlatNode> hoisted;
16 public void analyze(FlatMethod fm) {
17 loops=new LoopFinder(fm);
18 Loops root=loops.getRootLoop(fm);
19 table=new Hashtable<Loops, Set<FlatNode>>();
20 hoisted=new HashSet<FlatNode>();
21 usedef=new UseDef(fm);
22 posttree=new DomTree(fm,true);
26 public void recurse(Loops parent) {
27 processLoop(parent, parent.nestedLoops().size()==0);
28 for(Iterator lpit=parent.nestedLoops().iterator();lpit.hasNext();) {
29 Loops child=(Loops)lpit.next();
34 public void processLoop(Loops l, boolean isLeaf) {
37 Set elements=l.loopIncElements();
38 Set toprocess=l.loopIncElements();
39 toprocess.removeAll(hoisted);
41 HashSet<FieldDescriptor> fields=new HashSet<FieldDescriptor>();
42 HashSet<TypeDescriptor> types=new HashSet<TypeDescriptor>();
47 /* Check whether it is safe to reuse values. */
48 for(Iterator elit=elements.iterator();elit.hasNext();) {
49 FlatNode fn=elit.next();
50 if (fn.kind()==FKind.FlatAtomicEnterNode||
51 fn.kind()==FKind.FlatAtomicExitNode||
52 fn.kind()==FKind.Call) {
55 } else if (fn.kind()==FKind.FlatSetFieldNode) {
56 FlatSetFieldNode fsfn=(FlatSetFieldNode)fn;
57 fields.add(fsfn.getField());
58 } else if (fn.kind()==FKind.FlatSetElementNode) {
59 FlatSetElementNode fsen=(FlatSetElementNode)fn;
60 types.add(fsen.getDst().getType());
65 HashSet dominatorset=computeAlways(l);
67 /* Compute loop invariants */
68 table.put(l, new HashSet<FlatNode>());
72 for(Iterator tpit=toprocess.iterator();tpit.hasNext();) {
73 FlatNode fn=(FlatNode)tpit.next();
75 case FKind.FlatOpNode:
76 int op=((FlatOpNode)fn).getOperation();
77 if (op==Operation.DIV||op==Operation.MID||
78 checkNode(fn,elements)) {
83 case FKind.FlatInstanceOfNode:
84 if (checkNode(fn,elements)) {
89 case FKind.FlatElementNode:
90 if (unsafe||!dominatorset.contains(fn)||
91 checkNode(fn,elements))
93 TypeDescriptor td=((FlatElementNode)fn).getSrc().getType();
94 for(Iterator<TypeDescriptor> tpit=types.iterator();tpit.hasNext();) {
95 TypeDescriptor td2=tpit.next();
96 if (typeutil.isSuperorType(td,td2)||
97 typeutil.isSuperorType(td2,td)) {
103 case FKind.FlatFieldNode:
104 if (unsafe||!dominatorset.contains(fn)||
105 fields.contains(((FlatFieldNode)fn).getField())||
106 checkNode(fn,elements)) {
116 table.get(l).add(fn);
121 public HashSet computeAlways(Loops l) {
122 /* Compute nodes that are always executed in loop */
123 HashSet dominatorset=null;
125 /* Compute nodes that definitely get executed in a loop */
126 Set entrances=l.loopEntraces();
127 assert entrances.size()==1;
128 FlatNode entrance=(FlatNode)entrances.iterator().next();
130 for (int i=0;i<entrances.numPrev();i++) {
131 FlatNode incoming=entrence.getPrev(i);
132 if (elements.contains(incoming)) {
133 HashSet domset=new HashSet();
134 domset.add(incoming);
135 FlatNode tmp=incoming;
136 while(tmp!=entrance) {
137 tmp=domtree.idom(tmp);
145 for(Iterator it=dominatorset.iterator();it.hasNext();) {
146 FlatNode fn=(FlatNode)it.next();
147 if (!domset.containsKey(fn))
156 public boolean checkNode(FlatNode fn, Set elements) {
157 //Can hoist if all variables are loop invariant
158 TempDescriptor[]uses=fn.readsTemps();
159 for(int i=0;i<uses.length;i++) {
160 TempDescriptor t=uses[i];
161 Set<FlatNode> defset=usedef.defMap(fn, t);
162 for(Iterator<FlatNode> defit=defset.iterator();defit.hasNext();) {
163 FlatNode def=defit.next();
164 if (elements.contains(def)&&defset.size()>1)
166 if (elements.contains(def)&&!hoisted.contains(def))