RFR: 8316105: C2: Back to back Parse Predicates from different loops but with same deopt reason are wrongly grouped together [v3]

Christian Hagedorn chagedorn at openjdk.org
Wed Sep 20 11:10:27 UTC 2023


> [JDK-8305636](https://bugs.openjdk.org/browse/JDK-8305636) wrongly refactored the code that groups predicates into Predicate Blocks which leads to a wrong execution when hitting a trap. 
> 
> **Background**
> 
> In general, when a loop X is folded and its Parse Predicates end up above loop Y, we can reuse the Parse Predicates from loop X to create Runtime Predicates with for loop Y. If such a Runtime Predicate of loop Y is false during runtime, we trap and jump back to the start of the folded loop X above. This is fine because we have not executed any side effects of loop X or between loop X and Y:
> 
> - **(i)** There are no other CFG nodes with possible side effects between loop X and Y. Otherwise, the Parse Predicates of loop X are not directly above loop Y and are removed by `eliminate_useless_parse_predicates()`.
> - **(ii)** There can be no stores pinned at Parse Predicates (they are not hoisted out of a loop with range checks and invariant checks) except at the last one. This happens, for example, if loop X is fully unrolled and folded away in IGVN. A store is then no longer pinned at the folded `CountedLoopNode` but at the last Parse Predicate of loop X. If there are no other CFG nodes between loop X and Y, then the Parser Predicates from loop X end up just above loop Y. All Runtime Predicates created for loop Y with Parse Predicates from loop X will be executed before the pinned store at the last Parse Predicate (i.e. the loop entry).
> 
> **Problem**
> 
> In the test case, we have loop A that is fully unrolled and folded. Its Parse Predicates end up above loop B after IGVN. The only difference to the situation with loop X and Y in **(ii)** is that loop B still has a Loop Limit Check Parse Predicate:
> ![image](https://github.com/openjdk/jdk/assets/17833009/3089c174-0fb5-4154-b665-b57a5e6f0cb8)
> 
> - `40 Parse Predicate` and `51 Parse Predicate` are from loop A with the pinned `80 StoreL` from within the loop body of A (i.e. `lFld`).
> - `107 Parse Predicate` is from loop B.
> 
> When eliminating useless Parse Predicates, we should remove the Parse Predicates of loop A, because **(i)** is violated: We have a CFG node (e.g. `107 Parse Predicate`). between the loop B and the Parse Predicates of loop A. This, however, does not happen due to a bug: We wrongly group the back to back Loop Limit Check Parse Predicates `107 Parse Predicate` and `51 Parse Predicate` together as single Predicate Block. As a result, we keep `51 Parse Predicate` and `40 Parse Predicate`.
> 
> **Manifestation of ...

Christian Hagedorn has updated the pull request incrementally with one additional commit since the last revision:

  Update src/hotspot/share/opto/predicates.cpp
  
  Co-authored-by: Tobias Hartmann <tobias.hartmann at oracle.com>

-------------

Changes:
  - all: https://git.openjdk.org/jdk/pull/15764/files
  - new: https://git.openjdk.org/jdk/pull/15764/files/84cc0d5e..29e71c9a

Webrevs:
 - full: https://webrevs.openjdk.org/?repo=jdk&pr=15764&range=02
 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=15764&range=01-02

  Stats: 1 line in 1 file changed: 0 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/15764.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/15764/head:pull/15764

PR: https://git.openjdk.org/jdk/pull/15764


More information about the hotspot-compiler-dev mailing list