RFR: 8281122: [IR Framework] Cleanup IR matching code in preparation for JDK-8280378
Christian Hagedorn
chagedorn at openjdk.java.net
Fri Feb 18 13:47:45 UTC 2022
This patch does some restructurings and refactorings of the `IRMatcher.java` class in preparation for adding IR matching support on different compile phases with [JDK-8280378](https://bugs.openjdk.java.net/browse/JDK-8280378). There are no semantic changes of how IR matching is eventually done on regexes and how the results are checked with the `failOn` and `counts` constraints provided by the user. The only user-visible change is an improved output format of matching failures.
The old format also did not report a `counts` constraint failure correctly. It wrongly used the format of `failOn` failures which was misleading. This is also fixed by this patch.
**Example:**
@Test
@IR(counts = {IRNode.STORE_F, "!= 1"}) // fails
@IR(counts = {IRNode.STORE_F, "2", IRNode.LOAD_F, "> 1"}) // both constraints fail
public void test1() {
fFld = 4.2f;
}
@Test
@IR(failOn = IRNode.ALLOC, counts = {IRNode.STORE_F, ">= 2"}) // failOn and counts fail
public void test2() {
fFld = 4.2f;
o = new Object();
}
_Failure outputs:_
<details>
<summary>Old format</summary>
Failed IR Rules (3)
------------------
- Method "public void ir_framework.tests.Testi.test1()":
* @IR rule 1: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", "!= 1"}, applyIfNot={})"
- counts: Graph contains wrong number of nodes:
Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
Expected 1 but found 1 node:
25 StoreF === 5 7 24 21 [[ 16 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test1 @ bci:3 (line 48)
* @IR rule 2: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", "2", "(\\d+(\\s){2}(LoadF.*)+(\\s){2}===.*)", "> 1"}, applyIfNot={})"
- counts: Graph contains wrong number of nodes:
Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
Expected 2 but found 1 node:
25 StoreF === 5 7 24 21 [[ 16 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test1 @ bci:3 (line 48)
Regex 2: (\d+(\s){2}(LoadF.*)+(\s){2}===.*)
Expected 1 but found 0 nodes.
- Method "public void ir_framework.tests.Testi.test2()":
* @IR rule 1: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={"(.*precise .*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java)"}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", ">= 2"}, applyIfNot={})"
- failOn: Graph contains forbidden nodes:
Regex 1: (.*precise .*\R((.*(?i:mov|xorl|nop|spill).*|\s*|.*LGHI.*)\R)*.*(?i:call,static).*wrapper for: _new_instance_Java)
Matched forbidden node:
1a5 movq RSI, precise java/lang/Object: 0x00007fb188007318:Constant:exact * # ptr
1af call,static wrapper for: _new_instance_Java
- counts: Graph contains wrong number of nodes:
Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
Expected 2 but found 1 node:
25 StoreF === 5 7 24 21 [[ 19 236 36 179 220 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test2 @ bci:3 (line 55)
</details>
<details>
<summary>New format</summary>
Failed IR Rules (3) of Methods (2)
----------------------------------
1) Method "public void ir_framework.tests.Testi.test1()" - [Failed IR rules: 2]:
* @IR rule 1: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", "!= 1"}, applyIfNot={})"
- counts: Graph contains wrong number of nodes:
* Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
- Failed comparison: [found] 1 != 1 [given]
- Matched node:
* 25 StoreF === 5 7 24 21 [[ 16 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test1 @ bci:3 (line 48)
* @IR rule 2: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", "2", "(\\d+(\\s){2}(LoadF.*)+(\\s){2}===.*)", "> 1"}, applyIfNot={})"
- counts: Graph contains wrong number of nodes:
* Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
- Failed comparison: [found] 1 = 2 [given]
- Matched node:
* 25 StoreF === 5 7 24 21 [[ 16 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test1 @ bci:3 (line 48)
* Regex 2: (\d+(\s){2}(LoadF.*)+(\s){2}===.*)
- Failed comparison: [found] 0 > 1 [given]
- No nodes matched!
2) Method "public void ir_framework.tests.Testi.test2()" - [Failed IR rules: 1]:
* @IR rule 1: "@compiler.lib.ir_framework.IR(applyIf={}, applyIfAnd={}, failOn={"(.*precise .*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java)"}, applyIfOr={}, counts={"(\\d+(\\s){2}(StoreF.*)+(\\s){2}===.*)", ">= 2"}, applyIfNot={})"
- failOn: Graph contains forbidden nodes:
* Regex 1: (.*precise .*\R((.*(?i:mov|xorl|nop|spill).*|\s*|.*LGHI.*)\R)*.*(?i:call,static).*wrapper for: _new_instance_Java)
- Matched forbidden node:
* 1a5 movq RSI, precise java/lang/Object: 0x00007fd3c4007318:Constant:exact * # ptr
1af call,static wrapper for: _new_instance_Java
- counts: Graph contains wrong number of nodes:
* Regex 1: (\d+(\s){2}(StoreF.*)+(\s){2}===.*)
- Failed comparison: [found] 1 >= 2 [given]
- Matched node:
* 25 StoreF === 5 7 24 21 [[ 19 236 36 179 220 ]] @ir_framework/tests/Testi+12 *, name=fFld, idx=4; Memory: @ir_framework/tests/Testi:NotNull+12 *, name=fFld, idx=4; !jvms: Testi::test2 @ bci:3 (line 55)
</details>
**New class structure:**
The old `IRMatcher` class mixed different tasks such as parsing, IR annotation verification, IR matching and failure reporting together. This made it difficult to extend the existing code to add IR matching support on different compile phases. Therefore, the class was split to separate the different tasks:
- parser classes (`IREncodingParser`, `HotSpotPidFileParser`, `IRMethodParser` etc.)
- entity classes for the different parts of an `@IR` annotation (`IRMethod`, `IRRule`, `Counts`, `FailOn` etc.)
- match result classes for each entity class to provide a formatted failure message (`IRMethodMatchResult`, `IRRuleMatchResult` etc.)
The main structure of the new classes will be kept in JDK-8280378 but will be further improved to match the new needs.
**Testing:**
- Normal tier testing including tier5 and 6 where the IR framework tests are executed.
- Testing of this patch in Valhalla with tier1-3 + some Valhalla-specific stress testing
Thanks,
Christian
-------------
Commit messages:
- Improve format of reported nodes and IR method line with failure counts
- Fix report compilation output if no match with counts
- Add separate classes for handling empty compilation outputs
- More cleanups
- Update copyrights and minor things
- Some renaming and formatting cleanups
- Splitting HotSpotPidFileParser into separate classes
- Move IR matching classes into separate packages
- Fix TestIRMatching test
- Split List of Failures into FailOn and Counts MatchResult classes and rename Failure into RegexFailure + improve IR failure messages
- ... and 6 more: https://git.openjdk.java.net/jdk/compare/a4d20190...873a8282
Changes: https://git.openjdk.java.net/jdk/pull/7533/files
Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=7533&range=00
Issue: https://bugs.openjdk.java.net/browse/JDK-8281122
Stats: 3592 lines in 57 files changed: 2756 ins; 769 del; 67 mod
Patch: https://git.openjdk.java.net/jdk/pull/7533.diff
Fetch: git fetch https://git.openjdk.java.net/jdk pull/7533/head:pull/7533
PR: https://git.openjdk.java.net/jdk/pull/7533
More information about the hotspot-compiler-dev
mailing list