RFR: 8319793: C2 compilation fails with "Bad graph detected in build_loop_late" after JDK-8279888 [v9]
Christian Hagedorn
chagedorn at openjdk.org
Fri Jan 5 08:52:28 UTC 2024
On Wed, 3 Jan 2024 15:53:04 GMT, Roland Westrelin <roland at openjdk.org> wrote:
>> Range check smearing and range check predication make an array access
>> dependent on 2 (or more in the case of RC smearing) conditions. As a
>> consequence, if a range check can be eliminated because there's an
>> identical dominating range check, the control dependent nodes that
>> could float and become dependent on the dominating range check cannot
>> be allowed to float because there's a risk that they would then bypass
>> one of the checks that make the access legal.
>>
>> `IfNode::dominated_by()` and `PhaseIdealLoop::dominated_by()` have
>> logic to prevent this: nodes that are control dependent on a range
>> check or predicate are not allowed to float. This is however not
>> sufficient as demonstrated by the test cases.
>>
>> In `TestArrayAccessAboveRCAfterSmearingOrPredication.testRangeCheckSmearing()`:
>>
>>
>> v += array[i];
>> if (flag2) {
>> if (flag3) {
>> field = 0x42;
>> }
>> }
>> if (flagField == 1) {
>> v += array[i];
>> }
>>
>>
>> The range check for the second `array[i]` load is replaced by the
>> dominating range check for the first `array[i]` but because the second
>> `array[i]` load could really be dependent on multiple range checks (in
>> case smearing happened which is not the case here), c2 doesn't allow
>> the second `array[i]` to float when the second range check is
>> removed. The second `array[i]` is then control dependent on:
>>
>>
>> if (flagField == 1) {
>>
>>
>> which is next found to be dominated by the same test:
>>
>>
>> if (flag == 1) {
>>
>>
>> and is removed. However nothing in `dominated_by()` treats node
>> dependent on tests that are not range check or predicates
>> specially. So the second `array[i]` is allowed to float and become
>> dependent on:
>>
>>
>> if (flag == 1) {
>>
>>
>> which is above the range check for that access. The test method in its
>> last invocation is passed an index for the array access that's widely
>> out of range. The array load happens before the range check and
>> crashes the VM. `testLoopPredication()` is a similar test where array
>> loads become dependent on predicates and end up above range checks.
>>
>> `TestArrayAccessCastIIAboveRC.java` is the test case from the bug
>> where for similar reasons a range check `CastII` ends up above its
>> range check, becomes top because its input becomes some integer that
>> conflicts with its...
>
> Roland Westrelin has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 11 commits:
>
> - Merge branch 'master' into JDK-8319793
> - review
> - Revert "Update src/hotspot/share/opto/castnode.hpp"
>
> This reverts commit 356c91cca911ed486f9f87f3eff53ce21e1e3ec9.
> - Revert "Update src/hotspot/share/opto/memnode.hpp"
>
> This reverts commit bdb731ea562f314f44d327f7243ef5cf9ad40b2e.
> - review
> - Update src/hotspot/share/opto/memnode.hpp
>
> Co-authored-by: Christian Hagedorn <christian.hagedorn at oracle.com>
> - Update src/hotspot/share/opto/castnode.hpp
>
> Co-authored-by: Christian Hagedorn <christian.hagedorn at oracle.com>
> - Update src/hotspot/share/opto/castnode.cpp
>
> Co-authored-by: Christian Hagedorn <christian.hagedorn at oracle.com>
> - Update src/hotspot/share/opto/ifnode.cpp
>
> Co-authored-by: Christian Hagedorn <christian.hagedorn at oracle.com>
> - Merge branch 'master' into JDK-8319793
> - ... and 1 more: https://git.openjdk.org/jdk/compare/15519285...dbe3c4c1
src/hotspot/share/opto/loopopts.cpp line 345:
> 343:
> 344: if (dp == nullptr)
> 345: return;
Since we bail out above if `iff->outcnt() != 2` (can it even be that we have an `If` at this point which does not have 2 out projections?) this bailout seems redundant. Looks like it was only added due to a parfait report with https://github.com/openjdk/jdk/commit/25c4a7fccdbdaa9da0a7aa5e04e80966138fe42c. Maybe we can remove that as well and change `proj_out_or_null()` back to `proj_out()` (not sure though if parfait will then report this again). But could also be done separately.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/16886#discussion_r1442626740
More information about the hotspot-compiler-dev
mailing list