[16] RFR(M) 8252188: Crash in OrINode::Ideal(PhaseGVN*, bool)+0x8b9

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Wed Sep 9 14:57:04 UTC 2020


>> Similar strict check for constant shift is needed in OrVNode::Ideal 
>> routine in vectornode.cpp.
> 
> It took me some time to analyze your code for "lazy de-generation" of 
> Rotate vectors. As I understand you want to preserve scalar optimization 
> which creates Rotate nodes but have to revert it to keep vectorization 
> of java code.

Yes, the main motivation was to simplify the implementation: keep 
vectorization logic simple (just Rotate -> RotateV transformation) and 
don't mess with matching if RotateV is not supported (expand ideal nodes 
instead of adding special AD instructions).

> Method degenerate_vector_rotate() has is_Con() check and, in general, it 
> could be TOP because we do loop optimizations after vectorization. I 
> added isa_int() check and treat 'cnt' in other case as variable to do 
> transformation on 'else' branch and let sub-graph collapse there.
> I also refactor degenerate_vector_rotate() to make it compact.

Good point.

> Second, about OrVNode::Ideal(). I am not sure how safe it is without 
> additional investigation because currently it is not executed. Based on 
> comment it was added for VectorAPI which is experimental and not pushed 
> yet.
> The code is convoluted and does not match scalar Or::Ideal() code.
> 
> OrINode::Ideal() does next checks for left rotation:
>    if (Matcher::match_rule_supported(Op_RotateLeft) &&
>        lopcode == Op_LShiftI && ropcode == Op_URShiftI && in(1)->in(1) 
> == in(2)->in(1)) {
> 
> but OrVNode::Ideal() does:
>    if (Matcher::match_rule_supported_vector(Op_RotateLeftV, vec_len, bt) &&
>        ((ropcode == Op_LShiftVI && lopcode == Op_URShiftVI) ||
> 
> Why it checks RIGHT operator for LShiftV????
> 
> And asserts are contradicting:
>     assert(Op_RShiftCntV == in(1)->in(2)->Opcode(), "LShiftCntV operand 
> expected");
> 
> Was this code tested? My immediate reaction is simple delete it now and 
> add reworked and tested version back with EnableVectorSupport flag check 
> after VectorAPI is integrated.

Sounds good.

My feedback on OrVNode::Ideal() during 8248830 review was:

"> 6) Constant folding scenarios are covered in RotateLeft/RotateRight 
idealization, inferencing of vector rotate through OrV idealization 
covers the vector patterns generated though non SLP route i.e. VectorAPI.

I'm fine with keeping OrV::Ideal(), but I'm concerned with the general 
direction here - duplication of scalar transformations to lane-wise 
vector operations. It definitely won't scale and in a longer run it 
risks to diverge. Would be nice to find a way to automatically "lift" 
scalar transformations to vectors and apply them uniformly. But right 
now it is just an idea which requires more experimentation."

> Reworked version may use the same new rotate_shift() I added. I start 
> rewriting it but since I can't test it and I am not sure may be edges 
> are swapped indeed. I am suggesting to remove it.
> 
> Also VectorAPI should use Rotate vectors from start which we can 
> de-generation if not supported. So I am not sure how OrVNode::Ideal() 
> will be usefull for VEctorAPI too.

Though the API exposes rotation as a dedicated operation, users are free 
to code it explicitly with vector shifts and vector or. Basically, the 
situation is similar to scalar case: there are dedicated methods 
available (Long.rotateLeft/rotateRight), but users are free to code 
their own variant. And sometimes more general code shapes may degenerate 
into rotates (as a result of other optimizations).

And from Vector API implementation perspective, it is attractive to 
implement vector rotation purely in Java code as a composition of vector 
shifts/or operations rather than using JVM intrinsic for it.

So, there's a number of use cases when transformations on vector nodes 
becomes profitable.

> http://cr.openjdk.java.net/~kvn/8252188/webrev.01/

Looks good.

Best regards,
Vladimir Ivanov

> 
> About testing. I see you used a lot of -128, 128 and similar values 
> which are larger then bits in Java Integer and Long.
> But Java do masking of shift count by default before executing shift.
> I would prefer if something like 31 (or 63 for Long) were used instead. 
> Otherwise Rotate vectors are not generated and tested.
> 
> compiler/intrinsics/TestRotate.java calls verify() after each operation 
> as result it is really hard to see generated assembler. I think we 
> should at least exclude inlinining of verify().
> 
> I will work on tests and have an other update.
> 
> Thanks,
> Vladimir K
> 
> 
>>
>> Regards,
>> Jatin
>>
>>> -----Original Message-----
>>> From: hotspot-compiler-dev 
>>> <hotspot-compiler-dev-retn at openjdk.java.net> On
>>> Behalf Of Vladimir Kozlov
>>> Sent: Friday, September 4, 2020 3:14 AM
>>> To: hotspot compiler <hotspot-compiler-dev at openjdk.java.net>
>>> Subject: [16] RFR(M) 8252188: Crash in OrINode::Ideal(PhaseGVN*,
>>> bool)+0x8b9
>>>
>>> https://cr.openjdk.java.net/~kvn/8252188/webrev.00/
>>> https://bugs.openjdk.java.net/browse/JDK-8252188
>>>
>>> Code added by 8248830 [1] uses Node::is_Con() check when looking for
>>> constant shift values.
>>> Unfortunately it does not guarantee that it will be Integer constant
>>> because TOP node is also ConNode.
>>> I used C2 types to check and get shift values. I also refactor code to
>>> consolidate checks.
>>>
>>> Tested: tier1, hs-tier2, hs-tier3.
>>> Verified fix with replay file from bug report.
>>> I also checked that RotateBenchmark.java added by 8248830 still creates
>>> Rotate vectors after this fix.
>>>
>>> I created subtask to add new regerssion test later because this fix is
>>> urgent and I did not have time to prepare it.
>>>
>>> Thanks,
>>> Vladimir
>>>
>>> [1] https://bugs.openjdk.java.net/browse/JDK-8248830


More information about the hotspot-compiler-dev mailing list