8193935: RFR(S): Illegal countedLoops transformation

Nils Eliasson nils.eliasson at oracle.com
Tue Mar 20 11:49:03 UTC 2018


Hi Vladimir,


On 2018-03-19 22:31, Vladimir Kozlov wrote:
> Hi Nils,
>
> Do I miss something in explanation? The check you added should be true 
> for all normal loops:

Yes, I need to add some proper documentation for this.

>
> if (limit_t->_hi > incr_t->_hi) {
>   return false; // limit might be a value that incr never can reach
>
> Fro example:
>
> for (int i = 0; i < 10; i++) {}

This would be:

i1 <- 0;
loop:
i2 <- phi(0 , i3)
i3 <- add(i2, 1)
cmp (i3, 10)
jlt loop

inct_t is the type for i3 - IntType[0, 10]
limit_t is IntType[10, 10]

My case is something like:

void testMethod(int[] array){
    int i = 0;
   while (true)
       sum + = array[i];
       i++;
       i = i && 0x7fff;
   }
}

In this case incr_t is the type of i at the end of the loop (or before 
the loop-phi at the start)- which is IntType[0,0x7fff]

If array is longer than 0x8000 this code should never terminate. If 
array is shorter, it will get an AIOOB.

Counted loops transform this into:

    int j = 0;
   while (true) {
       sum += array[j];
       j++;
   }

Best  regards,
Nils

>
> 10 > 1 and you will not convert this loop into counted.
>
> Thanks,
> Vladimir
>
> On 3/19/18 2:17 AM, Nils Eliasson wrote:
>> Hi,
>>
>> This bug was found in mpegaudio hiding behind the loop predication. 
>> The Counted loop transformation may loose a significant truncation 
>> which changes the behaviour of the program.
>>
>> CountedLoopNode::match_incr_with_optional_truncation finds the 
>> truncation Op_AndI(0x7fff) and sets trunc_t = TypeInt::CHAR. However 
>> the program does not use it for a char truncation, but a accessing an 
>> array as a circular buffer. (Any other mask would have hidden this 
>> problem since char truncation is the only one matched).
>>
>> A loop is succesfully matched as a countedloop, and when the trip 
>> counter is cloned it drops the truncation. In the intended char-case 
>> that is ok. In this case the truncation prevents the program from 
>> hitting an AIOOB.
>>
>> In the general case, if a truncated loop counter is compared to an 
>> array length (or any variable) it must be provable that the array 
>> length is less than the truncation, and then the truncation can be 
>> omitted. If the array length can be longer, the exit may never be 
>> taken - the loop may never terminate, and a counted loop transform 
>> can not be performed.
>>
>> One additional topic of discussion is if we really want to do counted 
>> loop transformations with a RangeCheck as exit point. Especially if 
>> the profiling shows that the RangeCheck never fails. In the loop that 
>> fails there are multiple exits, many which are RangeChecks.
>>
>> For additional optimization opportunities we could consider rotating 
>> the loop until a normal compare is the loop exit condition.
>>
>>
>> Image of significant parts of node graph (the entire loop with its 
>> multiple exits, is omitted): 
>> http://cr.openjdk.java.net/~neliasso/8193935/mpegaudio.png
>>
>> bug: https://bugs.openjdk.java.net/browse/JDK-8193935
>>
>> webrev: http://cr.openjdk.java.net/~neliasso/8193935/webrev.01
>>
>>
>> Please review,
>>
>> Nils Eliasson
>>



More information about the hotspot-compiler-dev mailing list