CSE, loops, and array accesses

Andrew Haley aph at redhat.com
Thu Oct 1 10:27:46 UTC 2015


I'm looking at a failure to CSE the array base offset in this loop:

        for (int i = 0; i < array.length; i++) {
            res += array[i];
        }

 ;; B2: #       B2 B3 <- B1 B2  Loop: B2-B2 inner  Freq: 100.958

  0x000003ff9d1a1a30: add       xscratch1, x10, #0x10
  0x000003ff9d1a1a34: ldr       w13, [xscratch1,w11,sxtw #2]
  0x000003ff9d1a1a38: add       w11, w11, #0x1  ;*iinc
                                                ; - tests.ScalarReduce::test1 at 20 (line 22)

  0x000003ff9d1a1a3c: add       w0, w0, w13     ;*iadd
                                                ; - tests.ScalarReduce::test1 at 18 (line 23)

  0x000003ff9d1a1a40: cmp       w11, #0x64
  0x000003ff9d1a1a44: b.lt      0x000003ff9d1a1a30  ;*if_icmpge
                                                ; - tests.ScalarReduce::test1 at 9 (line 22)


The odd thing is that if I use Unsafe it's fine:

        for (int i = 0; i < array.length; i++) {
            long address = (((long) i) << 2) + base;
            res += UNSAFE.getInt(array, address);
        }

;; B2: #       B2 B3 <- B1 B2  Loop: B2-B2 inner  Freq: 101.004

  0x000003ff8d1a16c0: ldr       w13, [x10,w11,sxtw #2]
  0x000003ff8d1a16c4: add       w11, w11, #0x1  ;*iinc
                                                ; - tests.Tests::test1 at 34 (line 22)

  0x000003ff8d1a16c8: add       w0, w0, w13     ;*iadd
                                                ; - tests.Tests::test1 at 32 (line 24)

  0x000003ff8d1a16cc: cmp       w11, #0x64
  0x000003ff8d1a16d0: b.lt      0x000003ff8d1a16c0  ;*if_icmpge


So, something somewhere in the compiler is preventing the array base
offset from being detached from the actual memory access.  I can
understand why this is desirable on x86 where we have instructions
which can do base+offset+index, but I don't understand why CSE works
with Unsafe but not actual arrays.  Note that I had to disable
unrolling to demonstrate this simple test case.

So, why are arrays treated differently?

Thanks,
Andrew.


$ java -XX:-TieredCompilation  -XX:LoopMaxUnroll=1 -Xbootclasspath/a:/home/aph/NetBeansProjects/Tests/build/classes/ tests/ScalarReduce

package tests;

import sun.misc.Unsafe;

/**
 *
 * @author aph
 */
public class Tests {

    private static final Unsafe UNSAFE = Unsafe.getUnsafe();

    static final int[] array = new int[100];
    static long base = UNSAFE.arrayBaseOffset(array.getClass());
    static int test1() {
        int res = 0;
        for (int i = 0; i < array.length; i++) {
            long address = (((long) i) << 2) + base;
            res += UNSAFE.getInt(array, address);
        }
        return res;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        long foo = 0;
        for (int i = 0; i < 10000000; i++)
            foo += test1();
        if (foo != 0)
            System.out.println("");
    }

}


More information about the hotspot-compiler-dev mailing list