# HG changeset patch # User Doug Simon # Date 1387196613 -3600 # Node ID b1712d10c8ef86cb04e369ed2d7bbf07561e68b3 # Parent e3b0608d6ab8db2ec8d603e7c0f047db94b40d27 moved loads of constants out of loops diff -r e3b0608d6ab8 -r b1712d10c8ef graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CommonedConstantsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CommonedConstantsTest.java Mon Dec 16 10:44:34 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CommonedConstantsTest.java Mon Dec 16 13:23:33 2013 +0100 @@ -27,6 +27,7 @@ import org.junit.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.phases.common.*; /** * Tests any optimization that commons loads of non-inlineable constants. @@ -37,7 +38,7 @@ // A method where a constant is used on the normal and exception edge of a non-inlined call. // The dominating block of both usages is the block containing the call. - public static Object testSnippet(String[] arr, int i) { + public static Object test0Snippet(String[] arr, int i) { Object result = null; try { result = Array.get(arr, i); @@ -53,13 +54,70 @@ @Test public void test0() { // Ensure the exception path is profiled - ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(getMethod("testSnippet")); + ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(getMethod("test0Snippet")); javaMethod.reprofile(); - testSnippet(array, array.length); + test0Snippet(array, array.length); + + test("test0Snippet", array, 0); + test("test0Snippet", array, 2); + test("test0Snippet", array, 3); + test("test0Snippet", array, 1); + } + + public static final char[] alphabet = "abcdefghijklmnopqrstuvwxyz".toCharArray(); + + static int noninlineLength(char[] s) { + return s.length; + } + + /** + * A constant with usages before and after a non-inlined call. + */ + public static int test1Snippet(String s) { + if (s == null) { + return noninlineLength(alphabet) + 1; + } + char[] sChars = s.toCharArray(); + int count = 0; + for (int i = 0; i < alphabet.length && i < sChars.length; i++) { + if (alphabet[i] == sChars[i]) { + count++; + } + } + return count; + } - test("testSnippet", array, 0); - test("testSnippet", array, 2); - test("testSnippet", array, 3); - test("testSnippet", array, 1); + @Test + public void test1() { + getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); + test1Snippet(new String(alphabet)); + + test("test1Snippet", (Object) null); + test("test1Snippet", "test1Snippet"); + test("test1Snippet", ""); + } + + /** + * A constant with only usage in a loop. + */ + public static int test2Snippet(String s) { + char[] sChars = s.toCharArray(); + int count = 0; + for (int i = 0; i < alphabet.length && i < sChars.length; i++) { + if (alphabet[i] == sChars[i]) { + count++; + } + } + return count; + } + + @Test + public void test2() { + assert getSuites().getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); + test2Snippet(new String(alphabet)); + + test("test2Snippet", (Object) null); + test("test2Snippet", "test1Snippet"); + test("test2Snippet", ""); } } diff -r e3b0608d6ab8 -r b1712d10c8ef graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Dec 16 10:44:34 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Dec 16 13:23:33 2013 +0100 @@ -28,6 +28,7 @@ import static com.oracle.graal.lir.LIR.*; import static com.oracle.graal.lir.LIRValueUtil.*; import static com.oracle.graal.nodes.ConstantNode.*; +import static com.oracle.graal.phases.GraalOptions.*; import java.util.*; import java.util.Map.Entry; @@ -39,10 +40,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.BlockEndOp; -import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.StandardOp.LabelOp; -import com.oracle.graal.lir.StandardOp.NoOp; +import com.oracle.graal.lir.StandardOp.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; @@ -136,6 +134,19 @@ public String toString() { return block + "#" + op; } + + /** + * Removes the {@link #op} from its original location if it is still at that location. + */ + public void unpin(LIR lir) { + if (index >= 0) { + // Replace the move with a filler op so that the operation + // list does not need to be adjusted. + List instructions = lir.lir(block); + instructions.set(index, new NoOp(null, -1)); + index = -1; + } + } } private Map constantLoads; @@ -261,7 +272,6 @@ LoadConstant load = constantLoads.get(value); if (load == null) { int index = lir.lir(currentBlock).size(); - // loadedValue = newVariable(value.getPlatformKind()); loadedValue = emitMove(value); LIRInstruction op = lir.lir(currentBlock).get(index); constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op)); @@ -269,13 +279,7 @@ Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock); loadedValue = load.variable; if (dominator != load.block) { - if (load.index >= 0) { - // Replace the move with a filler op so that the operation - // list does not need to be adjusted. - List instructions = lir.lir(load.block); - instructions.set(load.index, new NoOp(null, -1)); - load.index = -1; - } + load.unpin(lir); } else { assert load.block != currentBlock || load.index < lir.lir(currentBlock).size(); } @@ -883,6 +887,19 @@ // Remove loads where all usages are in the same block. for (Iterator> iter = constantLoads.entrySet().iterator(); iter.hasNext();) { LoadConstant lc = iter.next().getValue(); + + // Move loads of constant outside of loops + if (OptScheduleOutOfLoops.getValue()) { + Block outOfLoopDominator = lc.block; + while (outOfLoopDominator.getLoop() != null) { + outOfLoopDominator = outOfLoopDominator.getDominator(); + } + if (outOfLoopDominator != lc.block) { + lc.unpin(lir); + lc.block = outOfLoopDominator; + } + } + if (lc.index != -1) { assert lir.lir(lc.block).get(lc.index) == lc.op; iter.remove();