RFR: 8323274: C2: array load may float above range check [v6]
Emanuel Peter
epeter at openjdk.org
Fri Feb 9 14:40:55 UTC 2024
On Fri, 9 Feb 2024 14:01:17 GMT, Roland Westrelin <roland at openjdk.org> wrote:
>> This PR includes 5 test cases in which an array load floats above its
>> range check and the resulting compiled code can be made to segfault by
>> passing an out of bound index to the test method. Each test case takes
>> advantage of a different transformation to make the array load happen
>> too early:
>>
>> For instance, with TestArrayAccessAboveRCAfterSplitIf:
>>
>>
>> if (k == 2) {
>> v = array1[i];
>> array = array1;
>> if (l == m) {
>> }
>> } else {
>> v = array2[i];
>> array = array2;
>> }
>> v += array[i]; // range check + array load
>>
>>
>> The range check is split through phi:
>>
>>
>> if (k == 2) {
>> v = array1[i];
>> array = array1;
>> if (l == m) {
>> }
>> // range check here
>> } else {
>> v = array2[i];
>> array = array2;
>> // range check here
>> }
>> v += array[i]; // array load
>>
>>
>> Then an identical dominating range check is found:
>>
>>
>> if (k == 2) {
>> v = array1[i]; // range check here
>> array = array1;
>> if (l == m) {
>> }
>> } else {
>> v = array2[i]; // range check here
>> array = array2;
>> }
>> v += array[i]; // array load
>>
>>
>> Then a branch dies:
>>
>>
>> v = array1[i]; // range check here
>> array = array1;
>> if (l == m) {
>> }
>> v += array[i]; // array load
>>
>>
>> The array load is dependent on the `if (l == m) {` condition. An
>> identical dominating condition is then found which causes the control
>> dependent range check to float above the range check.
>>
>> Something similar can be triggered with:
>>
>> - TestArrayAccessAboveRCAfterPartialPeeling: sometimes, during partial
>> peeling a load is assigned the loop head as control so something
>> gets in between the range check and an array load and steps similar
>> to the above can cause the array load to float above its range check.
>>
>> - TestArrayAccessAboveRCAfterUnswitching: cloning a loop body adds
>> regions on exits of the loop and nodes that only have uses out of
>> the loop can end up control dependent on one of the regions. In the
>> test case, unswitching is what causes the cloning to happen. Again
>> similar steps as above make the array load floats above its range
>> check. I suppose similar bugs could be triggered with other loop
>> transformations that rely on loop body cloning.
>>
>> TestArrayAccessAboveRCAfterSinking is a bit different in that it can
>> change the control of an array load to be the projection of some
>> arbitrary test. That test can then be replaced by a dominating one
>> causing t...
>
> Roland Westrelin has updated the pull request incrementally with one additional commit since the last revision:
>
> fix broken try_sink_out_of_loop
Thanks for the updates @rwestrel , looks good to me now 😊
-------------
Marked as reviewed by epeter (Reviewer).
PR Review: https://git.openjdk.org/jdk/pull/17635#pullrequestreview-1872549333
More information about the hotspot-compiler-dev
mailing list