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