https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86072

            Bug ID: 86072
           Summary: Poor codegen with atomics
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redbeard0531 at gmail dot com
  Target Milestone: ---

https://godbolt.org/g/aEFhq8

#include <atomic>

std::atomic<int> progress{-1};

void combine_writes1() {
    // These should be reduced to a single store(0,release),
    // At least as long as release-sequnce includes same-thread
    // relaxed stores. If that is removed, this should just be
    // a single relaxed store.
    progress.store(0, std::memory_order_relaxed);
    progress.store(0, std::memory_order_relaxed);
    progress.store(0, std::memory_order_release);
    progress.store(0, std::memory_order_release);
    progress.store(0, std::memory_order_relaxed);
    progress.store(0, std::memory_order_relaxed);
}

void combine_writes2() {
    // Ditto above, but should store 5.
    progress.store(0, std::memory_order_relaxed);
    progress.store(1, std::memory_order_relaxed);
    progress.store(2, std::memory_order_release);
    progress.store(3, std::memory_order_release);
    progress.store(4, std::memory_order_relaxed);
    progress.store(5, std::memory_order_relaxed);
}

void combine_loads() {
    // These should be reduced to either a single acquire-load
    // or an acquire fence. 
    progress.load(std::memory_order_relaxed);
    progress.load(std::memory_order_relaxed);
    progress.load(std::memory_order_acquire);
    progress.load(std::memory_order_acquire);
    progress.load(std::memory_order_relaxed);
    progress.load(std::memory_order_relaxed);
}

combine_writes1():
  xor eax, eax
  mov DWORD PTR progress[rip], eax
  mov DWORD PTR progress[rip], eax
  mov DWORD PTR progress[rip], eax
  mov DWORD PTR progress[rip], eax
  mov DWORD PTR progress[rip], eax
  mov DWORD PTR progress[rip], eax
  ret
combine_writes2():
  mov DWORD PTR progress[rip], 0
  mov DWORD PTR progress[rip], 1
  mov DWORD PTR progress[rip], 2
  mov DWORD PTR progress[rip], 3
  mov DWORD PTR progress[rip], 4
  mov DWORD PTR progress[rip], 5
  ret
combine_loads():
  mov eax, DWORD PTR progress[rip]
  mov eax, DWORD PTR progress[rip]
  mov eax, DWORD PTR progress[rip]
  mov eax, DWORD PTR progress[rip]
  mov eax, DWORD PTR progress[rip]
  mov eax, DWORD PTR progress[rip]
  ret
progress:
  .long -1

This example seems to ICE segfaulting gcc trunk: https://godbolt.org/g/M4ZQGS


Possibly related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86056

Reply via email to