soot.toolkits.graph.LoopNestTree Maven / Gradle / Ivy
/* Soot - a J*va Optimization Framework
* Copyright (C) 2007 Eric Bodden
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package soot.toolkits.graph;
import java.util.Collection;
import java.util.Comparator;
import java.util.TreeSet;
import soot.Body;
import soot.jimple.Stmt;
import soot.jimple.toolkits.annotation.logic.Loop;
import soot.jimple.toolkits.annotation.logic.LoopFinder;
/**
* A loop nesting tree, implemented as a tree-map.
* Loops are represented by pairs of head-statements and the respective loop.
* The iterator over this collection returns the loop in such an order that
* a loop l will always returned before a loop m if l is an inner loop of m.
*
* @author Eric Bodden
*/
public class LoopNestTree extends TreeSet {
/**
* Comparator, stating that a loop l1 is smaller than a loop l2 if l2 contains all statements of l1.
*
* @author Eric Bodden
*/
private static class LoopNestTreeComparator implements Comparator {
public int compare(Loop loop1, Loop loop2) {
Collection stmts1 = loop1.getLoopStatements();
Collection stmts2 = loop2.getLoopStatements();
if(stmts1.equals(stmts2)) {
assert loop1.getHead().equals(loop2.getHead()); //should really have the same head then
//equal (same) loops
return 0;
} else if(stmts1.containsAll(stmts2)) {
//1 superset of 2
return 1;
} else if(stmts2.containsAll(stmts1)) {
//1 subset of 2
return -1;
}
//overlap (?) or disjoint: order does not matter;
//however we must *not* return 0 as this would only keep one of the two loops;
//hence, return 1
return 1;
}
}
/**
* Builds a loop nest tree from a method body using {@link LoopFinder}.
*/
public LoopNestTree(Body b) {
this(computeLoops(b));
}
/**
* Builds a loop nest tree from a mapping from loop headers to statements in the loop.
*/
public LoopNestTree(Collection loops) {
super(new LoopNestTreeComparator());
addAll(loops);
}
private static Collection computeLoops(Body b) {
LoopFinder loopFinder = new LoopFinder();
loopFinder.transform(b);
Collection loops = loopFinder.loops();
return loops;
}
public boolean hasNestedLoops() {
//TODO could be speeded up by just comparing two consecutive
//loops returned by the iterator
LoopNestTreeComparator comp = new LoopNestTreeComparator();
for (Loop loop1 : this) {
for (Loop loop2 : this) {
if(comp.compare(loop1, loop2)!=0) {
return true;
}
}
}
return false;
}
}