Optimization question

Vladimir Kozlov vladimir.kozlov at oracle.com
Thu Dec 24 01:59:58 UTC 2015


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.

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();

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


More information about the hotspot-compiler-dev mailing list