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