public void terminateAnalysis() {
Loops loopFinder = loopInv.root;
- if (loopFinder.nestedLoops().size() > 0) {
- for (Iterator lpit = loopFinder.nestedLoops().iterator(); lpit.hasNext();) {
- Loops loop = (Loops) lpit.next();
- Set entrances = loop.loopEntrances();
- processLoop(fm, loop, loopInv);
- }
+ recurse(fm, loopFinder);
+ }
+
+ private void recurse(FlatMethod fm, Loops parent) {
+ for (Iterator lpit = parent.nestedLoops().iterator(); lpit.hasNext();) {
+ Loops child = (Loops) lpit.next();
+ processLoop(fm, child);
+ recurse(fm, child);
}
}
- public void processLoop(FlatMethod fm, Loops l, LoopInvariant loopInv) {
+ public void processLoop(FlatMethod fm, Loops l) {
boolean changed = true;
-
- Set elements = l.loopIncElements(); // loop body elements
- Set entrances = l.loopEntrances(); // loop entrance
- assert entrances.size() == 1;
- FlatNode entrance = (FlatNode) entrances.iterator().next();
-
- // mapping from Induction Variable TempDescriptor to Definiton Flat Node
+ inductionSet.clear();
+ Set loopElements = l.loopIncElements(); // loop body elements
+ Set loopEntrances = l.loopEntrances(); // loop entrance
+ assert loopEntrances.size() == 1;
+ FlatNode loopEntrance = (FlatNode) loopEntrances.iterator().next();
+
+ // mapping from Induction Variable TempDescriptor to Flat Node that defines
+ // it
Hashtable<TempDescriptor, FlatNode> inductionVar2DefNode =
new Hashtable<TempDescriptor, FlatNode>();
Set<FlatNode> computed = new HashSet<FlatNode>();
- // #1 find out basic induction variable
+ // 1) find out basic induction variable
// variable i is a basic induction variable in loop if the only definitions
// of i within L are of the form i=i+c where c is loop invariant
- for (Iterator elit = elements.iterator(); elit.hasNext();) {
+ for (Iterator elit = loopElements.iterator(); elit.hasNext();) {
FlatNode fn = (FlatNode) elit.next();
if (fn.kind() == FKind.FlatOpNode) {
FlatOpNode fon = (FlatOpNode) fn;
TempDescriptor tdLeft = fon.getLeft();
TempDescriptor tdRight = fon.getRight();
- boolean isLeftLoopInvariant = isLoopInvariantVar(l, fn, tdLeft);
- boolean isRightLoopInvariant = isLoopInvariantVar(l, fn, tdRight);
+ boolean isLeftLoopInvariant = isLoopInvariantVar(fn, tdLeft, loopElements);
+ boolean isRightLoopInvariant = isLoopInvariantVar(fn, tdRight, loopElements);
if (isLeftLoopInvariant ^ isRightLoopInvariant) {
candidateTemp = tdLeft;
}
- Set<FlatNode> defSetOfLoop = getDefinitionInsideLoop(l, fn, candidateTemp);
+ Set<FlatNode> defSetOfLoop = getDefinitionInLoop(fn, candidateTemp, loopElements);
// basic induction variable must have only one definition within the
// loop
if (defSetOfLoop.size() == 1) {
+ // find out definition of induction var, form of Flat
+ // Assign:inductionVar = candidateTemp
FlatNode indNode = defSetOfLoop.iterator().next();
assert indNode.readsTemps().length == 1;
TempDescriptor readTemp = indNode.readsTemps()[0];
if (readTemp.equals(fon.getDest())) {
inductionVar2DefNode.put(candidateTemp, defSetOfLoop.iterator().next());
inductionVar2DefNode.put(readTemp, defSetOfLoop.iterator().next());
- inductionSet.add(readTemp);
+ inductionSet.add(fon.getDest());
inductionSet.add(candidateTemp);
computed.add(fn);
}
}
}
- // #2 detect derived induction variables
+ // 2) detect derived induction variables
// variable k is a derived induction variable if
// 1) there is only one definition of k within the loop, of the form k=j*c
// or k=j+d where j is induction variable, c, d are loop-invariant
while (changed) {
changed = false;
- for (Iterator elit = elements.iterator(); elit.hasNext();) {
+ nextfn: for (Iterator elit = loopElements.iterator(); elit.hasNext();) {
FlatNode fn = (FlatNode) elit.next();
if (!computed.contains(fn)) {
if (fn.kind() == FKind.FlatOpNode) {
TempDescriptor tdRight = fon.getRight();
TempDescriptor tdDest = fon.getDest();
- boolean isLeftLoopInvariant = isLoopInvariantVar(l, fn, tdLeft);
- boolean isRightLoopInvariant = isLoopInvariantVar(l, fn, tdRight);
+ boolean isLeftLoopInvariant = isLoopInvariantVar(fn, tdLeft, loopElements);
+ boolean isRightLoopInvariant = isLoopInvariantVar(fn, tdRight, loopElements);
if (isLeftLoopInvariant ^ isRightLoopInvariant) {
TempDescriptor inductionOp;
// find new derived one k
if (!basicInductionSet.contains(inductionOp)) {
+ // in this case, induction variable 'j' is derived from
+ // basic induction var
+
// check if only definition of j that reaches k is the one
// in the loop
- Set defSet = getDefinitionInsideLoop(l, fn, inductionOp);
+
+ Set<FlatNode> defSet = getDefinitionInLoop(fn, inductionOp, loopElements);
if (defSet.size() == 1) {
// check if there is no def of i on any path bet' def of j
// and def of k
FlatNode defk = fn;
if (!checkPath(defI, defJ, defk)) {
- continue;
+ continue nextfn;
}
}
}
// add new induction var
+ // when tdDest has the form of srctmp(tdDest) = inductionOp +
+ // loopInvariant
+ // want to have the definition of srctmp
Set<FlatNode> setUseNode = loopInv.usedef.useMap(fn, tdDest);
assert setUseNode.size() == 1;
assert setUseNode.iterator().next().writesTemps().length == 1;
- TempDescriptor derivedInd = setUseNode.iterator().next().writesTemps()[0];
- FlatNode defNode = setUseNode.iterator().next();
+ FlatNode srcDefNode = setUseNode.iterator().next();
+ if (srcDefNode instanceof FlatOpNode) {
+ if (((FlatOpNode) srcDefNode).getOp().getOp() == Operation.ASSIGN) {
+ TempDescriptor derivedIndVar = setUseNode.iterator().next().writesTemps()[0];
+ FlatNode defNode = setUseNode.iterator().next();
+
+ computed.add(fn);
+ computed.add(defNode);
+ inductionSet.add(derivedIndVar);
+ inductionVar2DefNode.put(derivedIndVar, defNode);
+ derivedVar2basicInduction.put(derivedIndVar, inductionOp);
+ changed = true;
+ }
+ }
- computed.add(fn);
- computed.add(defNode);
- inductionSet.add(derivedInd);
- inductionVar2DefNode.put(derivedInd, defNode);
- derivedVar2basicInduction.put(derivedInd, inductionOp);
- changed = true;
}
}
}
}
+
// #3 check condition branch
// In the loop, every guard condition of the loop must be composed by
// induction & invariants
Set<FlatNode> tovisit = new HashSet<FlatNode>();
Set<FlatNode> visited = new HashSet<FlatNode>();
- tovisit.add(entrance);
+ tovisit.add(loopEntrance);
- int countLoopGuardCondtion = 0;
- int countLoop = 0;
+ int numMustTerminateGuardCondtion = 0;
+ int numLoop = 0;
while (!tovisit.isEmpty()) {
FlatNode fnvisit = tovisit.iterator().next();
tovisit.remove(fnvisit);
FlatCondBranch fcb = (FlatCondBranch) fnvisit;
if (fcb.isLoopBranch()) {
- countLoop++;
+ numLoop++;
}
- if (fcb.isLoopBranch() || hasLoopExitNode(fcb, true, entrance, elements)) {
+ if (fcb.isLoopBranch() || hasLoopExitNode(fcb, true, loopEntrance, loopElements)) {
// current FlatCondBranch can introduce loop exits
// in this case, guard condition of it should be composed only by loop
// invariants and induction variables
- Set<FlatNode> condSet = getDefinitionInsideLoop(l, fnvisit, fcb.getTest());
+ Set<FlatNode> condSet = getDefinitionInLoop(fnvisit, fcb.getTest(), loopElements);
assert condSet.size() == 1;
FlatNode condFn = condSet.iterator().next();
// assume that guard condition node is always a conditional inequality
FlatOpNode condOp = (FlatOpNode) condFn;
// check if guard condition is composed only with induction
// variables
- if (checkConditionNode(l, condOp, fcb.isLoopBranch())) {
- countLoopGuardCondtion++;
+ if (checkConditionNode(condOp, fcb.isLoopBranch(), loopElements)) {
+ numMustTerminateGuardCondtion++;
+ } else {
+ if (!fcb.isLoopBranch()) {
+ // if it is if-condition and it leads us to loop exit,
+ // corresponding guard condition should be composed by induction
+ // and invariants
+ throw new Error("Loop may never terminate at "
+ + fm.getMethod().getClassDesc().getSourceFileName() + "::"
+ + loopEntrance.numLine);
+ }
}
}
}
for (int i = 0; i < fnvisit.numNext(); i++) {
FlatNode next = fnvisit.getNext(i);
- if (!visited.contains(next)) {
+ if (loopElements.contains(next) && !visited.contains(next)) {
tovisit.add(next);
}
}
// # of must-terminate loop condition must be equal to or larger than # of
// loop
- if (countLoopGuardCondtion < countLoop) {
+ if (numMustTerminateGuardCondtion < numLoop) {
throw new Error("Loop may never terminate at "
- + fm.getMethod().getClassDesc().getSourceFileName() + "::" + entrance.numLine);
+ + fm.getMethod().getClassDesc().getSourceFileName() + "::" + loopEntrance.numLine);
}
}
return true;
}
- private boolean checkConditionNode(Loops l, FlatOpNode fon, boolean isLoopCondition) {
+ private boolean checkConditionNode(FlatOpNode fon, boolean isLoopCondition, Set loopElements) {
// check flatOpNode that computes loop guard condition
// currently we assume that induction variable is always getting bigger
// and guard variable is constant
}
// here, verify that guard operand is an induction variable
- if (!hasInductionVar(l, fon, induction)) {
+ if (!hasInductionVar(fon, induction, loopElements)) {
return false;
}
if (guard != null) {
- Set guardDefSet = getDefinitionInsideLoop(l, fon, guard);
+ Set guardDefSet = getDefinitionInLoop(fon, guard, loopElements);
for (Iterator iterator = guardDefSet.iterator(); iterator.hasNext();) {
FlatNode guardDef = (FlatNode) iterator.next();
if (!(guardDef instanceof FlatLiteralNode) && !loopInv.hoisted.contains(guardDef)) {
return true;
}
- private boolean hasInductionVar(Loops l, FlatNode fn, TempDescriptor td) {
+ private boolean hasInductionVar(FlatNode fn, TempDescriptor td, Set loopElements) {
// check if TempDescriptor td has at least one induction variable and is
// composed only by induction vars +loop invariants
return true;
} else {
// check if td is composed by induction variables or loop invariants
- Set<FlatNode> defSet = getDefinitionInsideLoop(l, fn, td);
+ Set<FlatNode> defSet = getDefinitionInLoop(fn, td, loopElements);
for (Iterator iterator = defSet.iterator(); iterator.hasNext();) {
FlatNode defNode = (FlatNode) iterator.next();
int inductionVarCount = 0;
TempDescriptor[] readTemps = defNode.readsTemps();
for (int i = 0; i < readTemps.length; i++) {
- if (!hasInductionVar(l, defNode, readTemps[i])) {
- if (!isLoopInvariantVar(l, defNode, readTemps[i])) {
+ if (!hasInductionVar(defNode, readTemps[i], loopElements)) {
+ if (!isLoopInvariantVar(defNode, readTemps[i], loopElements)) {
return false;
}
} else {
}
- private boolean isLoopInvariantVar(Loops l, FlatNode fn, TempDescriptor td) {
+ private boolean isLoopInvariantVar(FlatNode fn, TempDescriptor td, Set loopElements) {
- Set elements = l.loopIncElements();
Set<FlatNode> defset = loopInv.usedef.defMap(fn, td);
Set<FlatNode> defSetOfLoop = new HashSet<FlatNode>();
for (Iterator<FlatNode> defit = defset.iterator(); defit.hasNext();) {
FlatNode def = defit.next();
- if (elements.contains(def)) {
+ if (loopElements.contains(def)) {
defSetOfLoop.add(def);
}
}
}
- private Set<FlatNode> getDefinitionInsideLoop(Loops l, FlatNode fn, TempDescriptor td) {
+ private Set<FlatNode> getDefinitionInLoop(FlatNode fn, TempDescriptor td, Set loopElements) {
Set<FlatNode> defSetOfLoop = new HashSet<FlatNode>();
- Set loopElements = l.loopIncElements();
Set defSet = loopInv.usedef.defMap(fn, td);
for (Iterator iterator = defSet.iterator(); iterator.hasNext();) {
private boolean hasLoopExitNode(FlatCondBranch fcb, boolean fromTrueBlock, FlatNode loopHeader,
Set loopElements) {
-
if (!fromTrueBlock) {
// in this case, FlatCondBranch must have two next flat node, one for true
// block and one for false block
tovisit.remove(fn);
visited.add(fn);
- // check if this loop exit is derived from start node
- // if not, it has an exit in regarding to the loop header
- if (!loopElements.contains(fn)) {
- return true;
- }
-
for (int i = 0; i < fn.numNext(); i++) {
FlatNode next = fn.getNext(i);
if (!visited.contains(next)) {
+ // check that if-body statment introduces loop exit.
+ if (!loopElements.contains(next)) {
+ return true;
+ }
+
if (loopInv.domtree.idom(next).equals(fn)) {
// add next node only if current node is immediate dominator of the
// next node
tovisit.add(next);
- }
+ }
}
}