RFR: 8267265: Use new IR Test Framework to create tests for C2 IGV transformations [v4]
Christian Hagedorn
chagedorn at openjdk.java.net
Fri Sep 17 12:25:53 UTC 2021
On Wed, 1 Sep 2021 00:23:11 GMT, John Tortugo <github.com+2249648+JohnTortugo at openjdk.org> wrote:
>> Hi, can I please get some reviews for this Pull Request? Here is a summary of the changes:
>>
>> - Add tests, using the new IR-based test framework, for several of the Ideal transformations on Add, Sub, Mul, Div, Loop nodes and some simple Scalar Replacement transformations.
>> - Add more default IR regex's to IR-based test framework.
>> - Changes to Sub, Div and Add Ideal nodes to that transformations on Int and Long types are the whenever possible same.
>> - Changes to Sub*Node, Div*Node and Add*Node Ideal methods to fix some bugs and include new transformations.
>> - New JTREG "ir_transformations" test group under test/hotspot/jtreg.
>
> John Tortugo has updated the pull request incrementally with 146 additional commits since the last revision:
>
> - Fix merge mistake.
> - Merge branch 'jdk-8267265' of https://github.com/JohnTortugo/jdk into jdk-8267265
> - Addressing PR feedback: move tests to other directory, add custom tests, add tests for other optimizations, rename some tests.
> - 8273197: ProblemList 2 jtools tests due to JDK-8273187
> 8273198: ProblemList java/lang/instrument/BootClassPath/BootClassPathTest.sh due to JDK-8273188
>
> Reviewed-by: naoto
> - 8262186: Call X509KeyManager.chooseClientAlias once for all key types
>
> Reviewed-by: xuelei
> - 8273186: Remove leftover comment about sparse remembered set in G1 HeapRegionRemSet
>
> Reviewed-by: ayang
> - 8273169: java/util/regex/NegativeArraySize.java failed after JDK-8271302
>
> Reviewed-by: jiefu, serb
> - 8273092: Sort classlist in JDK image
>
> Reviewed-by: redestad, ihse, dfuchs
> - 8273144: Remove unused top level "Sample Collection Set Candidates" logging
>
> Reviewed-by: iwalulya, ayang
> - 8262095: NPE in Flow$FlowAnalyzer.visitApply: Cannot invoke getThrownTypes because tree.meth.type is null
>
> Co-authored-by: Jan Lahoda <jlahoda at openjdk.org>
> Co-authored-by: Vicente Romero <vromero at openjdk.org>
> Reviewed-by: jlahoda
> - ... and 136 more: https://git.openjdk.java.net/jdk/compare/ac430bf7...463102e2
Thanks for your effort to write tests for all these different kinds of transformations! Generally, they look good and are worth to have! You should add `@bug 8267265` to all files.
test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java line 34:
> 32: * @run driver compiler.c2.irTests.AddINodeIdealizationTests
> 33: */
> 34: public class AddINodeIdealizationTests {
General comments, also applies to the other test files:
It might be good to sanity check the output results of all these transformations (even though they are simple). Since the tests only use simple randomized ints, you could use a single `@Run` method instead of one for each test. This could look something like [this](https://gist.github.com/chhagedorn/b16aba260a8fcf27c082beccf2cec0a3).
test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java line 40:
> 38:
> 39: @Test
> 40: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.SUB})
In this test and all the following ones (including the other files), I think you can remove unrelated `failOn` regexes on operations that are not part of the test. For example, in this test you can safely remove `IRNode.MUL, DIV, and SUB`.
test/hotspot/jtreg/compiler/c2/irTests/AddINodeIdealizationTests.java line 91:
> 89: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.SUB})
> 90: @IR(counts = {IRNode.ADD, "2"})
> 91: // Checks (x + c1) + y => (x + y) + c1
Unfortunately, a limitation of the framework to check the correct inputs of IR nodes.
test/hotspot/jtreg/compiler/c2/irTests/AddLNodeIdealizationTests.java line 151:
> 149: return (a - b) + (c - a);
> 150: }
> 151:
Compared to the `AddI` tests, you've missed the case `(a - b) + (b - c) => (a - c)` here.
test/hotspot/jtreg/compiler/c2/irTests/DivINodeIdealizationTests.java line 44:
> 42: // Checks x / x => 1
> 43: public int constant(int x) {
> 44: return x / x;
This fails when `x` is zero with an `ArithmeticException`. I suggest to convert this into a custom run test and catch this case - maybe also testing zero as separate case to see if an exception is thrown with compiled code.
test/hotspot/jtreg/compiler/c2/irTests/DivINodeIdealizationTests.java line 68:
> 66: // Checks x / (y / y) => x
> 67: public int identityThird(int x, int y) {
> 68: return x / (y / y);
Same problem as above with `y = 0`.
test/hotspot/jtreg/compiler/c2/irTests/DivINodeIdealizationTests.java line 79:
> 77: // Hotspot should keep the division because it may cause a division by zero trap
> 78: public int retainDenominator(int x, int y) {
> 79: return (x * y) / y;
Same problem as above with `y = 0`.
test/hotspot/jtreg/compiler/c2/irTests/DivLNodeIdealizationTests.java line 34:
> 32: * @run driver compiler.c2.irTests.DivLNodeIdealizationTests
> 33: */
> 34: public class DivLNodeIdealizationTests {
Same div by zero problems as with `DivI`. Should be adjusted analogously.
test/hotspot/jtreg/compiler/c2/irTests/MulINodeIdealizationTests.java line 45:
> 43: //Checks Max(a,b) * min(a,b) => a*b
> 44: public int excludeMaxMin(int x, int y){
> 45: return Math.max(x, y) * Math.min(x, y);
`Math.min/max()` is intrinsified and HotSpot generates `CMove` nodes (see `LibraryCallKit::generate_min_max()`) for them. But it looks like `MulNode::Ideal` misses this check for `CMove` nodes. That could be done in a separate RFE (and then this test could be improved to check if the `CMove` node was removed).
Anyways, min/max nodes are mainly used for loop limit computations, so it's harder to test this transformation in an easy way.
test/hotspot/jtreg/compiler/c2/irTests/MulLNodeIdealizationTests.java line 43:
> 41: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.DIV, IRNode.CALL})
> 42: @IR(counts = {IRNode.MUL, "1"})
> 43: //Checks Max(a,b) * min(a,b) => a*b
See comments for `MulI`.
test/hotspot/jtreg/compiler/c2/irTests/SubINodeIdealizationTests.java line 164:
> 162: @Arguments(Argument.RANDOM_EACH)
> 163: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.SUB, IRNode.ADD})
> 164: // Checks 0 - (a >> 31) => a >> 31
Comment should be adjusted to differentiate between signed and unsigned shifts. And a rule should be added to check that the `RShiftI` node was converted into an `URShiftI` node.
test/hotspot/jtreg/compiler/c2/irTests/SubLNodeIdealizationTests.java line 155:
> 153: @Arguments(Argument.RANDOM_EACH)
> 154: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.SUB, IRNode.ADD})
> 155: // Checks 0 - (a >> 63) => a >>> 63
Same as for `SubI` above, a rule should be added for the shift nodes.
test/hotspot/jtreg/compiler/c2/irTests/loopOpts/LoopIdealizationTests.java line 43:
> 41: @Test
> 42: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.ADD, IRNode.SUB, IRNode.LOOP, IRNode.COUNTEDLOOP, IRNode.COUNTEDLOOP_MAIN, IRNode.CALL})
> 43: //Checks that a for loop with 0 iterations is removed
Missing space after `//` and also for other comments below.
test/hotspot/jtreg/compiler/c2/irTests/loopOpts/LoopIdealizationTests.java line 44:
> 42: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.ADD, IRNode.SUB, IRNode.LOOP, IRNode.COUNTEDLOOP, IRNode.COUNTEDLOOP_MAIN, IRNode.CALL})
> 43: //Checks that a for loop with 0 iterations is removed
> 44: public void zeroIterForLoop(){
Missing space between `)` and `{` and also on other lines below.
test/hotspot/jtreg/compiler/c2/irTests/loopOpts/LoopIdealizationTests.java line 52:
> 50: @Test
> 51: @IR(failOn = {IRNode.LOAD, IRNode.STORE, IRNode.MUL, IRNode.DIV, IRNode.ADD, IRNode.SUB, IRNode.LOOP, IRNode.COUNTEDLOOP, IRNode.COUNTEDLOOP_MAIN, IRNode.CALL})
> 52: //Checks that a for loop with 0 iterations is removed
Actually there is 1 iteration but we break it immediately (i.e. the loop is entered).
test/hotspot/jtreg/compiler/c2/irTests/loopOpts/LoopIdealizationTests.java line 89:
> 87: if (i == 0){
> 88: break;
> 89: }else{
Spaces around `else`.
test/hotspot/jtreg/compiler/c2/irTests/loopOpts/LoopIdealizationTests.java line 141:
> 139: //Checks that a while loop with 1 iteration is simplified to straight code
> 140: public void oneIterDoWhileLoop(){
> 141: do{
Spacing
test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/ScalarReplacementTests.java line 29:
> 27: /*
> 28: * @test
> 29: * @summary Tests that Escape Analisys and Scalar Replacement is able to handle some simple cases.
Typo: Analisys -> Analysis
test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/ScalarReplacementTests.java line 33:
> 31: * @run driver compiler.c2.irTests.scalarReplacement.ScalarReplacementTests
> 32: */
> 33: public class ScalarReplacementTests {
You should also add some rules to check if there is an allocation or not.
test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java line 162:
> 160: public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END;
> 161: public static final String MEMBAR = START + "MemBar" + MID + END;
> 162:
I suggest to move all newly added regex together here.
-------------
Changes requested by chagedorn (Reviewer).
PR: https://git.openjdk.java.net/jdk/pull/5135
More information about the hotspot-compiler-dev
mailing list