Optimization question

Vitaly Davidovich vitalyd at gmail.com
Thu Dec 24 02:13:33 UTC 2015


Hi Vladimir,

On Wednesday, December 23, 2015, Vladimir Kozlov <vladimir.kozlov at oracle.com>
wrote:

> Unfortunately whole loop unrolling happens after Escape analysis is done.
> As result we can't eliminate allocations since we don't know which element
> of arrays is referenced in loop:
>
> JavaObject NoEscape(NoEscape) NSR [ 397F 275F 276F 398F [ 197 202 ]]
>  185      AllocateArray   ===  127  124  178  8  1 ( 111  99  20  98  1
> 72  1  1  130  1
>
> NSR - Non Scalar Replaceable.
>
> After loop is unrolled the result is calculated but arrays are still
> allocated.


Ah ok, that's what Kris was saying as well.  But why does unrolling matter
for this purpose? Even if loop is not unrolled is it not known which
elements are accessed?

Also, what do you mean by "result is calculated"? What result? :)


> We do remove NSR allocations for boxing objects but not regular
> allocations:
>
>   // Eliminate boxing allocations which are not used
>   // regardless scalar replaceable status.
>   bool boxing_alloc = C->eliminate_boxing() &&
>                       tklass->klass()->is_instance_klass()  &&
>                       tklass->klass()->as_instance_klass()->is_box_klass();
>   if (!alloc->_is_scalar_replaceable && (!boxing_alloc || (res != NULL))) {
>     return false;
>   }
>
> Only allocation followed by arraycopy skips zeroing, not by fill() call.
> Arrays.fill() is implemented as loop.
>
>   if (init != NULL && init->is_complete_with_arraycopy() &&
>       k->is_type_array_klass()) {
>     // Don't zero type array during slow allocation in VM since
>     // it will be initialized later by arraycopy in compiled code.
>     slow_call_address = OptoRuntime::new_array_nozero_Java();


Hmm, I'm pretty sure fill() following an allocation had the same zeroing
elision applied to it.  Kris notes the opto is turned off due to
implementation issues, which would explain why I still see zeroing.

Thanks

>
> Regards,
> Vladimir
>
> On 12/23/15 4:56 PM, Vitaly Davidovich wrote:
>
>> Hi guys,
>>
>> Consider code like this:
>>
>> static double mean(double[] array, double[] weights) {
>>       if (array.length != weights.length) throw ...;
>>       double sum = 0;
>>       double wsum = 0;
>>       for(int i = 0; i < array.length; i++) {
>>            sum += array[i] * weights[i];
>>            wsum += weights[i];
>>        }
>>        return sum / wsum;
>> }
>>
>> static double mean(double[] array) {
>>       return mean(array, allOnes(array.length));
>> }
>>
>> static double[] allOnes(int n) {
>>       double[] d = new double[n];
>>       Arrays.fill(d, 1);
>>       return d;
>> }
>>
>> Now suppose I call mean(double[]) overload like this:
>>
>> double[] d = {1,2,3,4};
>>
>> Using 8u51 with C2 compiler:
>>
>> 1) it looks like the array allocation from allOnes isn't eliminated.
>> 2) moreover it looked like array was zeroed (rep stosd with rax holding
>> zero).  Unless I misread the asm, I thought an
>> allocation followed by Arrays.fill skips the zeroing?
>> 3) ideally, this case would reduce to code that just does a plain
>> unweighted mean with no multiplication by the weight
>> and no summation for the weighted sum (weight sum is just array length).
>> Is this simply too much analysis to ask for?
>>
>> Thanks
>>
>>
>> --
>> Sent from my phone
>>
>

-- 
Sent from my phone
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20151223/a77be499/attachment-0001.html>


More information about the hotspot-compiler-dev mailing list