This is an archive of the discontinued LLVM Phabricator instance.

[X86] Fold (setcc (cmp (atomic_load_add x, -C) C), COND) to (setcc (LADD x, -C), COND) (PR31367)
ClosedPublic

Authored by hans on Dec 14 2016, 3:34 PM.

Details

Summary

This targets a pattern that occurrs frequently with reference counting pointers:

void decrement(long volatile *ptr) {
  if (_InterlockedDecrement(ptr) == 0)
    release();
}

Clang would previously compile it (for 32-bit at -Os) as:

00000000 <?decrement@@YAXPCJ@Z>:
   0:   8b 44 24 04             mov    0x4(%esp),%eax
   4:   31 c9                   xor    %ecx,%ecx
   6:   49                      dec    %ecx
   7:   f0 0f c1 08             lock xadd %ecx,(%eax)
   b:   83 f9 01                cmp    $0x1,%ecx
   e:   0f 84 00 00 00 00       je     14 <?decrement@@YAXPCJ@Z+0x14>
  14:   c3                      ret

and with this patch it becomes:

00000000 <?decrement@@YAXPCJ@Z>:
   0:   8b 44 24 04             mov    0x4(%esp),%eax
   4:   f0 ff 08                lock decl (%eax)
   7:   0f 84 00 00 00 00       je     d <?decrement@@YAXPCJ@Z+0xd>
   d:   c3                      ret

(Equivalent variants with _InterlockedExchangeAdd, std::atomic<>'s fetch_add or pre-decrement operator generate the same code.)

Diff Detail

Repository
rL LLVM

Event Timeline

hans updated this revision to Diff 81486.Dec 14 2016, 3:34 PM
hans retitled this revision from to [X86] Fold (setcc (cmp (atomic_load_add x, -C) C), COND) to (setcc (LADD x, -C), COND) (PR31367).
hans updated this object.
hans added a reviewer: rnk.
hans added subscribers: llvm-commits, thakis.
rnk accepted this revision.Dec 14 2016, 4:07 PM
rnk edited edge metadata.

We stared at this for a while and convinced ourselves that it is correct. (cmp X C) should produce the same flags as (sub X C), and (atomic_load_add X -C) should produce the flags of (sub X C).

This revision is now accepted and ready to land.Dec 14 2016, 4:07 PM
This revision was automatically updated to reflect the committed changes.