RFR: 8371603: C2: assert(_inputs.at(alias_idx) == nullptr || _inputs.at(alias_idx) == load->in(1)) failed

Xiaohong Gong xgong at openjdk.org
Thu Dec 4 10:19:16 UTC 2025


On Thu, 4 Dec 2025 08:08:14 GMT, Emanuel Peter <epeter at openjdk.org> wrote:

>> **Problem:**
>> 
>> This issue occurs on a 256-bit SVE machine, caused by the following problematic pattern in `LoadVectorNode::Ideal()`:
>> 
>> 
>> Node* LoadVectorNode::Ideal(PhaseGVN* phase, bool can_reshape) {
>>   const TypeVect* vt = vect_type();
>>   if (Matcher::vector_needs_partial_operations(this, vt)) {
>>     return VectorNode::try_to_gen_masked_vector(phase, this, vt);
>>   }
>>   return LoadNode::Ideal(phase, can_reshape);
>> }
>> 
>> 
>> The condition `Matcher::vector_needs_partial_operations(this, vt)` returns true for `LoadVectorNode` with 256-bit vector size even when the vector size equals the maximum vector size on SVE. In such cases, when `VectorNode::try_to_gen_masked_vector()` returns `nullptr`, the method exits early without calling `LoadNode::Ideal()`. This results in missing crucial optimizations that would normally be applied by the superclass.
>> 
>> This code was introduced by https://bugs.openjdk.org/browse/JDK-8286941 to generate vector masks for partial vector operations, but it failed to ensure that the superclass `Ideal()` method is always invoked when no transformation is applied.
>> 
>> **Solution:**
>> 
>> This patch addresses the issue through two changes:
>> 
>> 1. Refine `Matcher::vector_needs_partial_operations()` to return true only when the vector node genuinely represents a partial vector operation that requires masking.
>> 2. Modify `VectorNode::try_to_gen_masked_vector()` to never return `nullptr`, ensuring the superclass `Ideal()` method is always invoked when no transformation is applied.
>> 
>> **Testing:**
>> 
>> - Verified on different SVE platforms with different vector sizes (128|256|512 bits).
>> - Verified on X86 platforms with different avx options (-XX:UseAVX=1|2|3).
>> - Added two new IR tests to verify 1) previously missing optimizations for `LoadVector/StoreVector` are now applied, and 2) that mask and the correct IR patterns are generated for partial vector operations.
>
> src/hotspot/share/opto/vectornode.cpp line 1118:
> 
>> 1116:   if (Matcher::vector_needs_partial_operations(this, vt)) {
>> 1117:     return VectorNode::gen_masked_vector(phase, this, vt);
>> 1118:   }
> 
> I think it would still be good practice to expect that a `nullptr` could come from `gen_masked_vector`, and then continue with optimizations below, rather than just returning the `nullptr`.
> 
> Because: who knows what someone in the future might do inside `gen_masked_vector`, maybe they'll find some edge case and just return `nullptr` again, and then we are back to similar issues.

I see your concern. Make sense to me. Thanks! I'd like keep current implementation of `Matcher::vector_needs_partial_operations` and `gen_masked_vector` because as we discussed in the previous PR that this sounds more reasonable. 

I will update the caller code here to check `nullptr` in addition although it won't generate a `nullptr` now. Code may look like:

if (Matcher::vector_needs_partial_operations(this, vt)) {
    Node* n = VectorNode::gen_masked_vector(phase, this, vt);
    if (n != nullptr) {
      return n;
    }
 }
return ...

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

PR Review Comment: https://git.openjdk.org/jdk/pull/28651#discussion_r2588404849


More information about the hotspot-compiler-dev mailing list