RFR: 8342047: Create Template Assertion Predicates with Halt nodes only instead of uncommon traps
Christian Hagedorn
chagedorn at openjdk.org
Tue Nov 12 15:33:53 UTC 2024
This patch replaces the creation of Template Assertion Predicates with uncommon traps with Halt nodes.
### Goal of Assertion Predicates
#### Initialized Assertion Predicates
These predicates ensure that control is properly folded when data is dying. They are **always true by design** and thus can never fail at runtime. We therefore put a halt node on the failing path.
#### Template Assertion Predicates
Only serve as templates to create Initialized Assertion Predicates from. They are never executed and are always removed after loop opts are over. Conceptionally, it does not matter whether the failing path uses an UCT or a halt node (or something else completely - I plan to have a separate "no-op" `TemplateAssertionPredicateNode` at some point which only falls through to the next node and does not have a failing path at all).
### Why Did we Use UCTs for Template Assertion Predicates?
When the concept of Assertion Predicates was first introduced, it only covered a few edge cases. It was quite straight forward to reuse existing Loop Predication code which creates new predicates from a Parse Predicate by copying it and merging the UCTs on the failing paths with a region node. This was done with `PhaseIdealLoop::create_new_if_for_predicate()`.
### Why Do we Need to Use Halt Nodes for Template Assertion Predicates?
#### Missing UCTs for Predicates above Loops
Over time, we found more cases where we need to create Initialized Assertion Predicates from templates - including locations where we do not have Parse Predicates (and thus no safepoints). For example, when peeling one iteration off a loop with Parse Predicates, they will be kept at the peeled iteration and the remaining loop does not have any Parse Predicates anymore.
#### Missing UCTs to Create Template Assertion Predicates
Whenever we split a loop with Template Assertion Predicates, we also need to ensure that they are copied to all split loop versions. Since they rely on using UCTs, we also need to make sure that an UCT/safepoint is available to be used. However, this is not always the case (for example, after peeling an iteration off as described in the last section). As a result, we cannot easily establish new Template Assertion Predicates anywhere. One could think about faking an UCT or doing other special logic. But this seems rather fragile and could introduce quite some complexity - especially since we conceptionally don't even need to use UCTs at all for Template Assertion Predicates.
There is already some special logic for a main loop, where we create Template Assertion Predicates with a Halt node because there is no UCT available for the main loop. But this logic and implementation it is not easily reusable and we would need to keep supporting both formats with UCTs and halt nodes.
### Solution: Assertion Predicates with Halt Nodes only
As a simple solution to the problems described above, I propose to get rid of UCTs completely. This not only enables us to fix the remaining unresolved bugs where Assertion Predicates are missing but also simplifies the logic and the IR itself.
I've added some comments in the PR to better explain the refactoring steps.
Thanks,
Christian
-------------
Commit messages:
- 8342047: Create Template Assertion Predicates with Halt nodes only instead of uncommon traps
Changes: https://git.openjdk.org/jdk/pull/22040/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=22040&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8342047
Stats: 205 lines in 6 files changed: 30 ins; 77 del; 98 mod
Patch: https://git.openjdk.org/jdk/pull/22040.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/22040/head:pull/22040
PR: https://git.openjdk.org/jdk/pull/22040
More information about the hotspot-compiler-dev
mailing list