/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.max.graal.compiler.loop;
import java.util.*;
import com.oracle.max.graal.graph.*;
import com.oracle.max.graal.nodes.*;
public class LoopUtil {
public static LoopInfo computeLoopInfo(Graph graph) {
// Create node-to-loop relation.
NodeMap<Loop> nodeToLoop = graph.createNodeMap();
for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) {
mark(begin, nodeToLoop);
}
List<Loop> rootLoops = new ArrayList<Loop>(1);
LoopInfo info = new LoopInfo(nodeToLoop, rootLoops);
// Get parent-child relationships between loops.
for (LoopBeginNode begin : graph.getNodes(LoopBeginNode.class)) {
Loop loop = nodeToLoop.get(begin);
Loop parentLoop = nodeToLoop.get(begin.forwardEdge());
if (parentLoop != null) {
parentLoop.addChildren(loop);
} else {
rootLoops.add(loop);
}
}
//Find exits
for (Loop loop : info.loops()) {
for (FixedNode n : loop.fixedNodes()) {
if (n instanceof ControlSplitNode) {
for (BeginNode sux : ((ControlSplitNode) n).blockSuccessors()) {
if (!loop.containsFixed(sux)) {
loop.exits().mark(sux);
}
}
}
}
}
return info;
}
private static void mark(LoopBeginNode begin, NodeMap<Loop> nodeToLoop) {
if (nodeToLoop.get(begin) != null) {
// Loop already processed.
return;
}
Loop loop = new Loop(begin);
nodeToLoop.set(begin, loop);
NodeFlood workCFG = begin.graph().createNodeFlood();
workCFG.add(begin.loopEnd());
for (Node n : workCFG) {
if (n == begin) {
// Stop at loop begin.
continue;
}
markNode(n, loop, nodeToLoop);
for (Node pred : n.cfgPredecessors()) {
workCFG.add(pred);
}
}
// We finished marking the loop.
loop.setFinished();
}
private static void markNode(Node n, Loop loop, NodeMap<Loop> nodeToLoop) {
Loop oldMark = nodeToLoop.get(n);
if (oldMark == null || !oldMark.isFinished()) {
// We have an inner loop, start marking it.
if (n instanceof LoopBeginNode) {
mark((LoopBeginNode) n, nodeToLoop);
} else {
if (oldMark != null) {
oldMark.directCFGNode().clear(n);
}
nodeToLoop.set(n, loop);
loop.directCFGNode().mark(n);
}
}
}
}