RFR: 8288204: GVN Crash: assert() failed: correct memory chain [v2]

Tobias Hartmann thartmann at openjdk.org
Thu Dec 8 11:41:04 UTC 2022


On Mon, 10 Oct 2022 06:56:28 GMT, Yi Yang <yyang at openjdk.org> wrote:

>> Hi can I have a review for this fix? LoadBNode::Ideal crashes after performing GVN right after EA. The bad IR is as follows:
>> 
>> ![image](https://user-images.githubusercontent.com/5010047/183106710-3a518e5e-0b59-4c3c-aba4-8b6fcade3519.png)
>> 
>> The memory input of Load#971 is Phi#1109 and the address input of Load#971 is AddP whose object base is CheckCastPP#335:
>> 
>> The type of Phi#1109 is `byte[int:>=0]:exact+any *` while `byte[int:8]:NotNull:exact+any *,iid=177`  is the type of CheckCastPP#335 due to EA, they have different alias index, that's why we hit the assertion at L226:
>> 
>> https://github.com/openjdk/jdk/blob/b17a745d7f55941f02b0bdde83866aa5d32cce07/src/hotspot/share/opto/memnode.cpp#L207-L226
>> (t is `byte[int:>=0]:exact+any *`, t_adr is  `byte[int:8]:NotNull:exact+any *,iid=177`).
>> 
>> There is a long story. In the beginning, LoadB#971 is generated at array_copy_forward, and GVN transformed it iteratively:
>> 
>>  971  LoadB  ===  1115  1046  969  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  1109  969  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  1109  969  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  1109  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>> ...
>> 
>> In this case, we get alias index 5 from address input AddP#969, and step it through MergeMem#1046, we found Phi#1109 then, that's why LoadB->in(Mem) is changed from MergeMem#1046 to Phi#1109 (Which finally leads to crash).
>> 
>> 1046  MergeMem  === _  1  160  389  389  1109  1  1  389  1  1  1  1  1  1  1  1  1  1  1  1  1  709  709  709  709  882  888  894  190  190  912  191  [[ 1025  1021  1017  1013  1009  1005  1002  1001  998  996  991  986  981  976  971  966  962  961  960  121  122  123  124  1027 ]]  
>> 
>> 
>> After applying this patch, some related nodes are pushed into the GVN worklist, before stepping through MergeMem#1046, the address input is already changed to AddP#473. i.e., we get alias index 32 from address input AddP#473, and step it through MergeMem#1046, we found StoreB#191 then,LoadB->in(Mem) is changed from MergeMem#1046 to StoreB#191. 
>> 
>>  971  LoadB  ===  1115  1046  969  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  1046  969  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  1046  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  1115  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  468  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  468  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>>  971  LoadB  ===  390  191  473  [[ 972 ]]  @byte[int:8]:NotNull:exact+any *,iid=177, idx=32; #byte !jvms: String::coder @ bci:0 (line 4540) String::getBytes @ bci:1 (line 4453) StringConcatHelper::prepend @ bci:21 (line 354) StringConcatHelper::simpleConcat @ bci:81 (line 425) DirectMethodHandle$Holder::invokeStatic @ bci:11 DelegatingMethodHandle$Holder::reinvoke_L @ bci:14 Invokers$Holder::linkToTargetMethod @ bci:6 Test::test @ bci:121 (line 22)
>> ...
>> 
>> The well-formed IR looks like this:
>> ![image](https://user-images.githubusercontent.com/5010047/183239456-7096ea66-6fca-4c84-8f46-8c42d10b686a.png)
>> 
>> Thanks for your patience.
>
> Yi Yang has updated the pull request incrementally with one additional commit since the last revision:
> 
>   fix

Overall, the fix looks reasonable to me. I added some comments.

Please merge with master, currently the build fails with:

src/hotspot/share/opto/type.cpp:4920:16: error: no declaration matches 'const TypePtr* TypeAryPtr::with_offset(int) const'
[2022-12-08T10:34:55,711Z]  4920 | const TypePtr *TypeAryPtr::with_offset(int offset) const {
[2022-12-08T10:34:55,711Z]       |                ^~~~~~~~~~
[2022-12-08T10:34:55,711Z] /src/hotspot/share/opto/type.cpp:4892:19: note: candidate is: 'virtual const TypeAryPtr* TypeAryPtr::with_offset(intptr_t) const'
[2022-12-08T10:34:55,711Z]  4892 | const TypeAryPtr* TypeAryPtr::with_offset(intptr_t offset) const {

src/hotspot/share/opto/memnode.cpp line 225:

> 223:         t->is_oopptr()->cast_to_exactness(true)
> 224:           ->is_oopptr()->cast_to_ptr_type(t_oop->ptr())
> 225:             ->is_oopptr()->cast_to_instance_id(t_oop->instance_id());

I would prefer this formatting, similar to the assert.

Suggestion:

        t->is_oopptr()->cast_to_exactness(true)
         ->is_oopptr()->cast_to_ptr_type(t_oop->ptr())
         ->is_oopptr()->cast_to_instance_id(t_oop->instance_id());

src/hotspot/share/opto/memnode.cpp line 230:

> 228:                       ->cast_to_size(t_oop->is_aryptr()->size())
> 229:                         ->with_offset(t_oop->is_aryptr()->offset())
> 230:                           ->is_aryptr();

Do we need `cast_to_stable` as well here?

src/hotspot/share/opto/type.cpp line 4616:

> 4614: }
> 4615: 
> 4616: const TypePtr *TypeAryPtr::with_offset(int offset) const {

I think you can use the existing
https://github.com/openjdk/jdk/blob/49b86224aacc7fd8b4d3354a85d72ef636a18a12/src/hotspot/share/opto/type.cpp#L4892

test/hotspot/jtreg/compiler/c2/TestGVNCrash.java line 30:

> 28:  * @summary GVN Crash: assert() failed: correct memory chain
> 29:  *
> 30:  * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestGVNCrash::test compiler.c2.TestGVNCrash

This does not reproduce the issue with latest JDK 20, please add `-Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN` and `@key stress randomness`.

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

Changes requested by thartmann (Reviewer).

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


More information about the hotspot-compiler-dev mailing list