# HG changeset patch # User Christian Humer # Date 1412009200 -7200 # Node ID f735aa886cf660610dc6880aa738a76053c4e3f5 # Parent 88d5fd9e1a6c7d45fbab4a3e46f311b116575b6b Truffle: add new inlining tests; adapt tests for context sensitive inlining. diff -r 88d5fd9e1a6c -r f735aa886cf6 graal/com.oracle.graal.truffle.test/sl/TestInlining.sl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestInlining.sl Mon Sep 29 18:46:40 2014 +0200 @@ -0,0 +1,20 @@ +/* + * This tests that simple arithmetic gets inlined. + */ +function add(a, b) { + return a + b; +} + + +function test() { + i = 0; + while (i < 100) { + i = add(i, 1); + } + return i; +} + +function main() { + waitForOptimization(callUntilOptimized(test)); + assertTrue(isInlined(test, test, add), "add is not inlined"); +} diff -r 88d5fd9e1a6c -r f735aa886cf6 graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl --- a/graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl Mon Sep 29 18:46:38 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/sl/TestInliningMaxCallerSize.sl Mon Sep 29 18:46:40 2014 +0200 @@ -19,8 +19,8 @@ function main() { waitForOptimization(callUntilOptimized(test1)); - assertTrue(isInlined(test1, inlinableFunction), "inlinableFunction is not inlined"); + assertTrue(isInlined(test1, test1, inlinableFunction), "inlinableFunction is not inlined"); waitForOptimization(callUntilOptimized(test2)); - assertFalse(isInlined(test2, notInlinableFunction), "notInlinableFunction is inlined"); + assertFalse(isInlined(test2, test2, notInlinableFunction), "notInlinableFunction is inlined"); } diff -r 88d5fd9e1a6c -r f735aa886cf6 graal/com.oracle.graal.truffle.test/sl/TestInliningRecursive1.sl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestInliningRecursive1.sl Mon Sep 29 18:46:40 2014 +0200 @@ -0,0 +1,25 @@ +/* + * Test recursive calls do not get inlined and do not crash. + */ +function fib(a) { + if (a == 2 || a == 1) { + return 1; + } + return fib(a-1) + fib(a-2); +} + +function test() { + i = 0; + sum = 0; + while (i < 100) { + sum = sum + fib(7); + i = i + 1; + } + return sum; +} + +function main() { + waitForOptimization(callUntilOptimized(test)); + assertTrue(isInlined(test, test, fib), "fib is not inlined"); + assertFalse(isInlined(test, fib, fib), "fib -> fib is not inlined"); +} diff -r 88d5fd9e1a6c -r f735aa886cf6 graal/com.oracle.graal.truffle.test/sl/TestInliningRecursive2.sl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle.test/sl/TestInliningRecursive2.sl Mon Sep 29 18:46:40 2014 +0200 @@ -0,0 +1,37 @@ +/* + * Tests that indirect recursions are not inlined. + */ +function fib(a) { + if (a == 2 || a == 1) { + return 1; + } + return call(fib, a-1) + call(fib, a-2) + call(void, 0); +} + +function call(f, a) { + return f(a); +} + +function void(a) { + return a; +} + +function test() { + i = 0; + sum = 0; + while (i < 100) { + sum = sum + fib(7); + i = i + 1; + } + return sum; +} + +function main() { + waitForOptimization(callUntilOptimized(test)); + assertTrue(isInlined(test, test, fib), "not inlined: test -> fib"); + if (getOption("TruffleContextSensitiveInlining")) { + assertTrue(isInlined(test, fib, call), "not inlined: fib -> call"); + assertFalse(isInlined(test, call, fib), "inlined: call -> fib"); + assertTrue(isInlined(test, call, void), "inlined: call -> void"); + } +} diff -r 88d5fd9e1a6c -r f735aa886cf6 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsInlinedBuiltin.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsInlinedBuiltin.java Mon Sep 29 18:46:38 2014 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/builtins/SLIsInlinedBuiltin.java Mon Sep 29 18:46:40 2014 +0200 @@ -40,28 +40,57 @@ @Specialization @SlowPath - public Object isInlined(SLFunction parent, SLFunction inlinedFunction) { - boolean allFalse = true; - boolean allTrue = true; - for (OptimizedCallTarget parentTarget : findDuplicateCallTargets((OptimizedCallTarget) parent.getCallTarget())) { - Set callNodes = findCallsTo(parentTarget.getRootNode(), (OptimizedCallTarget) inlinedFunction.getCallTarget()); - for (DirectCallNode directCall : callNodes) { - if (directCall.isInlined()) { - allFalse = false; - } else { - allTrue = false; - } + public Object isInlined(SLFunction rootFunction, SLFunction parentFunction, SLFunction inlinedFunction) { + InliningTrace trace = new InliningTrace(); + + for (OptimizedCallTarget target : findDuplicateCallTargets((OptimizedCallTarget) rootFunction.getCallTarget())) { + if (target.isValid()) { + searchInlined(trace, target, new ArrayList<>(), parentFunction, inlinedFunction); } } - if (allFalse && allTrue) { - throw new AssertionError(String.format("No calls found from %s to %s .", parent, inlinedFunction)); - } else if (!allFalse && !allTrue) { - throw new AssertionError(String.format("Some calls from %s to %s are inlined and some are not.", parent, inlinedFunction)); + + if (trace.allFalse && trace.allTrue) { + throw new AssertionError(String.format("No optimized calls found from %s to %s .", parentFunction, inlinedFunction)); + } else if (!trace.allFalse && !trace.allTrue) { + throw new AssertionError(String.format("Some optimized calls from %s to %s are inlined and some are not.", parentFunction, inlinedFunction)); } - if (allTrue) { + if (trace.allTrue) { return true; } else { return false; } } + + private void searchInlined(InliningTrace trace, OptimizedCallTarget rootTarget, List stack, SLFunction parent, SLFunction inlinedFunction) { + OptimizedCallTarget root; + if (stack.isEmpty()) { + root = rootTarget; + } else { + root = stack.get(stack.size() - 1).getCurrentCallTarget(); + } + + for (OptimizedDirectCallNode callNode : root.getCallNodes()) { + stack.add(callNode); + + boolean inlined = rootTarget.isInlined(stack); + if (callNode.getRootNode().getCallTarget() == parent.getCallTarget() && callNode.getCallTarget() == inlinedFunction.getCallTarget()) { + if (inlined) { + trace.allFalse = false; + } else { + trace.allTrue = false; + } + } + + if (inlined) { + searchInlined(trace, rootTarget, stack, parent, inlinedFunction); + } + + stack.remove(stack.size() - 1); + } + } + + private static final class InliningTrace { + boolean allFalse = true; + boolean allTrue = true; + } }