Generated code oddity: redundant dereference?
Dean Long
dean.long at oracle.com
Sat Jul 6 19:56:00 PDT 2013
Looks like a glitch. "lea" is more like an add than a load, because it
computes the effective address
and stores it in a register.
dl
On 7/5/2013 5:24 AM, Aleksey Shipilev wrote:
> Hi,
>
> I was digging into assembly, and stumbled upon the peculiar pattern in
> one of the hot loops [1]:
>
> lea (%r12,%rdx,8),%r13
> lea 0xc(%r12,%rdx,8),%r13
>
> The first LEA seems redundant, since we kill the %r13 right afterwards.
> Is this the implicit null check? If so, isn't the same effect gained by
> second LEA?
>
> I see sometimes [2] it takes the form of:
>
> lea (%r12,%rdx,8),%rdi
> lea 0xc(%r12,%rdx,8),%r13
>
> With %rdi not used anywhere.
>
> Is this just the glitch in code generation, or that code bears some
> meaning I'm failing to grasp?
>
> -Aleksey.
>
> [1] This code:
>
> public static class Shared {
> public final AtomicReference<Object> ref =
> new AtomicReference<Object>();
> }
>
> public void test_Ref_Spin2(Shared shared) {
> while (!isDone) {
> shared.ref.getAndSet(CURRENT);
> }
> }
>
> compiles into
>
> 0x00007ff16d06f650: mov 0xc(%rbx),%r8d ; load ref
> 0x00007ff16d06f654: test %r8d,%r8d ; null check
> 0x00007ff16d06f657: je 0x00007ff16d06f70d ;
> 0x00007ff16d06f65d: lea (%r12,%r8,8),%r11 ; ???
> 0x00007ff16d06f661: lea 0xc(%r12,%r8,8),%r11 ; load &ref.value
> 0x00007ff16d06f666: mov $0xf5a79651,%r8d ; load CURRENT
> 0x00007ff16d06f66c: xchg %r8d,(%r11) ; CAS
> 0x00007ff16d06f66f: add $0x1,%rbp ; operations++
> 0x00007ff16d06f673: shr $0x9,%r11 ; CARD MARK
> 0x00007ff16d06f677: mov %r12b,(%r10,%r11,1) ; CARD MARK
> 0x00007ff16d06f67b: movzbl 0x8c(%r9),%r8d ; load isDone
> 0x00007ff16d06f683: test %eax,0xc786977(%rip) ; safepoint
> 0x00007ff16d06f689: test %r8d,%r8d ; isDone?
> 0x00007ff16d06f68c: je 0x00007ff16d06f650 ; <back branch>
>
>
> [2] This code:
>
> public static class Shared {
> public final AtomicReference<Object> ref =
> new AtomicReference<Object>();
> }
>
> public void test_Ref_Spin(Shared shared) {
> AtomicReference<Object> ref = shared.ref;
> while (!isDone) {
> Object cur;
> do {
> cur = ref.get();
> } while (!ref.compareAndSet(cur, CURRENT));
> }
> }
>
> compiles into:
>
> 0x00007f712fbeb24c: mov 0xc(%rbx),%edx ; load ref
> 0x00007f712fbeb24f: test %edx,%edx ; null check
> 0x00007f712fbeb251: je 0x00007f712fbeb31c ;
> 0x00007f712fbeb257: lea (%r12,%rdx,8),%rdi ; implicit null?
> 0x00007f712fbeb25b: lea 0xc(%r12,%rdx,8),%r13 ; load &ref.value
> 0x00007f712fbeb260: mov 0x0(%r13),%eax ; load ref.value
> 0x00007f712fbeb264: lock cmpxchg %ecx,0x0(%r13) ; CAS
> 0x00007f712fbeb26a: sete %r11b ; check the result
> 0x00007f712fbeb26e: movzbl %r11b,%r11d ; ...into r11
> 0x00007f712fbeb272: mov %r13,%r10 ; !!! card mark !!!
> 0x00007f712fbeb275: shr $0x9,%r10 ; !!! card mark !!!
> 0x00007f712fbeb279: mov %r12b,(%rsi,%r10,1) ; !!! card mark !!!
> 0x00007f712fbeb27d: test %r11d,%r11d ; CAS successful?
> 0x00007f712fbeb280: je 0x00007f712fbeb330 ; ...then <return>
> 0x00007f712fbeb286: movzbl 0x8c(%r8),%r10d ; load isDone
> 0x00007f712fbeb28e: add $0x1,%rbp ; operations++
> 0x00007f712fbeb292: test %eax,0xa71fd68(%rip) ; safepoint poll
> 0x00007f712fbeb298: test %r10d,%r10d ; isDone?
> 0x00007f712fbeb29b: je 0x00007f712fbeb24c ; <back branch>
More information about the hotspot-compiler-dev
mailing list