RFR: 8310308: IR Framework: check for type and size of vector nodes
Emanuel Peter
epeter at openjdk.org
Tue Jun 27 11:56:27 UTC 2023
For some changes to `SuperWord`, and maybe auto-vectorization in general, I want to strengthen the IR Framework.
**Motivation**
I want to not just find the relevant IR nodes, but also assert that they have the maximal length that they could have on the respective platform (given the CPU features and `MaxVectorSize`). Without this verification it is possible that a future change leads to a regression where we still vectorize but at shorter vector widths as before - leading to performance loss.
**How to use it**
All `IRNode`s in `test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java` that are created with `vectorNode` are now all matched with their `type` and `size`. The regex might now look something like this:
`"(\d+(\s){2}(VectorCastF2X.*)+(\s){2}===.*vector[A-Za-z][8]:{int})"`
which would match with IR nodes dumped like that:
`1150 VectorCastF2X === _ 1151 [[ 1146 ]] #vectory[8]:{int} ...`
The goal was to keep it simple and straight forward. In most cases, you can just use the nodes as before, and implicitly we now check for maximal size automatically. However, in some cases we want to ensure there is no or only a limited number of nodes (`failOn` or comparison `<` or `<=` or `=0`) - in those cases we usually want to make sure there is not any node of any size, so we match with any size by default. The size can also explicitly be constrained using `IRNode.VECTOR_SIZE`.
Some examples:
1. `@IR(counts = {IRNode.LOAD_VI, " >0 "})` -> search for a `LoadVector` node with `type` `int`, and maximal `size` possible on the machine (limited by CPU features and `MaxVectorSize`). This is the most common use case.
2. `@IR(failOn = { IRNode.LOAD_VL, IRNode.STORE_VECTOR })` -> fail if there is a `LoadVector` with type `long`, of `any` size.
3. `@IR(counts = { IRNode.XOR_VI, IRNode.VECTOR_SIZE_4, " > 0 "})` -> find at least one `XorV` node with type `int` and exactly `4` elements. Useful for VectorAPI when the vector species is fixed.
4. `@IR(counts = { IRNode.LOAD_VD, IRNode.VECTOR_SIZE + "min(4, max_double)", " >0 " })` -> search for a `LoadVector` node with `type` `double`, and `size` exactly equals to `min(4, max_double)` (so 4 elements, or if the hardware allows fewer `doubles`, then that number).
5. `@IR(counts = { IRNode.ABS_VF, IRNode.VECTOR_SIZE + "min(LoopMaxUnroll, max_float)", ">= 1" })` -> find at least one `AbsV` nodes with type `float`, and the `size` exactly equals to the smaller of `LoopMaxUnroll` or the maximal size allowed for `floats` (useful for tests where the `LoopMaxUnroll` is artificially lowered, which sometimes prevents the maximal filling of vectors).
6. `@IR(counts = {IRNode.VECTOR_CAST_I2F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0"})` -> find at least one `VectorCastI2X` node that casts to type `float`, and where the size is exactly equals to the smaller maximal size for `ints` and `floats`. This is helpful when there are multiple types in the loop, and the number of elements is limited by the sizes of multiple types.
I had to change lots of occurrences, hence you can find many more examples in the tests.
**Details**
Vector nodes that should be tested for `type` and `size` now are to be created with `VECTOR_PREFIX` and `vectorNode`, see `IRNode.java`.
When specifying such a `vectorNode` in an IR rule, one first uses the `irNodePlaceholder` (eg `Load_VI`), and following it one can optionally add a `IRNode.VECTOR_SIZE` specifier, which is then parsed by `parseVectorNodeSize`. This allows either naming a concrete size (eg `IRNode.VECTOR_SIZE_8`), a tag (`IRNode.VECTOR_SIZE + "<tag>"`) where the the tag can be one of the tags listed in `parseVectorNodeSizeTag`, or a `min(...)` clause which computes the minimum value of a comma separated list of tags. As a last resort one can match for any size (`IRNode.VECTOR_SIZE_ANY`).
The maximal vector size for any type is computed in `getMaxElementsForType`, under consideration of the CPU features and the `MaxVectorSize`.
**Changes to tests**
Unfortunately, I had to change a lot of IR rules, though not substantially. Most changes are because we usually had nodes like `MAX_V` or `LOAD_VECTOR` which matched for any type, and I had to create one node per type now (eg `MAX_VF, MAX_VD`, or `LOAD_VI, LOAD_VL, LOAD_VF, ...`). While this was a lot of work, it is still good to know that we are generating the nodes with the correct types.
In the VectorAPI tests there were many which required concrete sizes due to the concrete size of the vector species. This is nice to test, since it guarantees that the vector species indeed generate the expected vector sizes.
A few tests required more attention, where I had to use patterns like `IRNode.VECTOR_SIZE + "min(...)"`. These are especially interesting, as they test cases like mixed types (eg casting between types).
**Future Work**
There are a few nodes that I did not yet handle with `vectorNode` (eg `VECTOR_REINTERPRET`, `OR_V_MASK`, `MACRO_LOGIC_V`, `LOAD_VECTOR_GATHER(_MASKED)`). Some of these only have very few tests and are all from the Vector API which was not my priority here. They can easily be converted should the need arise in the future.
While looking at lots of IR tests I also came up with these RFE's:
[JDK-8310891](https://bugs.openjdk.org/browse/JDK-8310891) C2 SuperWord tests: move platform requirements to IR rules
[JDK-8310523](https://bugs.openjdk.org/browse/JDK-8310523) Add IR tests for nodes that have too few IR tests yet
[JDK-8310533](https://bugs.openjdk.org/browse/JDK-8310533) [IR Framework] Add possibility to automatically verify that a test method always returns the same result
**Testing**
tier1-tier6 and stress-testing **Running**.
-------------
Commit messages:
- fix whitespace
- fix 3 tests with old IRNode names
- vector cast
- VECTOR_CAST_I2X
- vector mask cmp and blend
- remove some remaining any size cases
- implement vector node min(...) tag parsing
- small refactoring
- cmove and bad format test
- Merge branch 'master' into JDK-8310308
- ... and 32 more: https://git.openjdk.org/jdk/compare/9057b350...1466083f
Changes: https://git.openjdk.org/jdk/pull/14539/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14539&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8310308
Stats: 3003 lines in 62 files changed: 943 ins; 16 del; 2044 mod
Patch: https://git.openjdk.org/jdk/pull/14539.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/14539/head:pull/14539
PR: https://git.openjdk.org/jdk/pull/14539
More information about the hotspot-compiler-dev
mailing list