Bug 91502 - suboptimal atomic_fetch_sub and atomic_fetch_add
Summary: suboptimal atomic_fetch_sub and atomic_fetch_add
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 9.2.1
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2019-08-20 16:51 UTC by Ruslan Nikolaev
Modified: 2021-12-21 16:47 UTC (History)
3 users (show)

See Also:
Host:
Target: x86_64-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-08-21 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ruslan Nikolaev 2019-08-20 16:51:35 UTC
I have not specified the gcc version; it seems like it applies to any version.

I have noticed that if I write code:

#include <stdatomic.h>

int func(_Atomic(int) *a)
{
        return (atomic_fetch_sub(a, 1) - 1 == 0);
}

gcc generates optimized code (gcc -O2):
func:
.LFB0:
        .cfi_startproc
        xorl    %eax, %eax
        lock subl       $1, (%rdi)
        sete    %al
        ret

But when I change the condition to <= 0, it does not work. Correct me if I am wrong, but, I think, it should still be able to use sub:

#include <stdatomic.h>

int func(_Atomic(int) *a)
{
        return (atomic_fetch_sub(a, 1) - 1 <= 0);

}

func:
.LFB0:
        .cfi_startproc
        movl    $-1, %eax
        lock xaddl      %eax, (%rdi)
        cmpl    $1, %eax
        setle   %al
        movzbl  %al, %eax
        ret

Seems like the same problem exists for atomic_fetch_add as well.
Comment 1 Ruslan Nikolaev 2019-08-20 18:19:12 UTC
btw, the same problem for

#include <stdatomic.h>

int func(_Atomic(long) *a)
{
        return (atomic_fetch_sub(a, 1) <= 0);
}

In the previous case clang/llvm was just like gcc, i.e., unable to optimize; in this case clang/llvm was able to produce better code, but gcc still cannot.
Comment 2 Richard Biener 2019-08-21 08:23:35 UTC
Confirmed.