[PATCH] D68964: cmake/modules/CheckAtomic.cmake: catch false positives in RISC-V

Gokturk Yuksek via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 07:49:05 PDT 2019


gokturk added a comment.

In D68964#1708804 <https://reviews.llvm.org/D68964#1708804>, @smeenai wrote:

> libc++ also has a version of this check (https://github.com/llvm/llvm-project/blob/master/libcxx/cmake/Modules/CheckLibcxxAtomic.cmake). Does that need to be adjusted as well?


It does create false positives. If I use the following code sample from the libcxx cmake test:

  #include <cstdint>
  #include <atomic>
  std::atomic<uintptr_t> x;
  std::atomic<uintmax_t> y;
  int main(int, char**) {
    return x + y;
  }

g++ compiles it just fine, with or without the 'A' extension defined (-march=rv64imafd vs -march=rv64imfd). It seems like g++ is inlining the following two functions in the binary:

  std::__atomic_base<unsigned long>::operator unsigned long() const;
  std::operator&(std::memory_order, std::__memory_order_modifier;

but performing the `x + y` as two sign-extended integer addition:

  ...
  # initialize and sign-extend x, store it in register s1
  jal	ra,3a8 <std::__atomic_base<unsigned long>::operator unsigned long() const>
  mv	a5,a0
  sext.w	s1,a5
  ...
  # Initialize and sign-extend y, store it in register a5
  jal	ra,3a8 <std::__atomic_base<unsigned long>::operator unsigned long() const>
  mv	a5,a0
  sext.w	a5,a5
  # Perform x + y, sign extend the result twice (??)
  addw	a5,s1,a5
  sext.w	a5,a5
  sext.w	a5,a5

As a result, no need for libatomic in the compilation. If I tweak the code sample a little bit so that `x + y` is a separate statement:

  #include <cstdint>
  #include <atomic>
  std::atomic<uintptr_t> x;
  std::atomic<uintmax_t> y;
  int main(int, char**) {
    x += y;
    return x;
  }

this still compiles fine under the 'A' extension:

  $ g++ -march=rv64imafd -std=c++11 -nostdlib libcxx-atomic-check.cpp 
  /usr/lib/gcc/riscv64-unknown-linux-gnu/9.1.0/../../../../riscv64-unknown-linux-gnu/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000000298

but fails without the 'A' extension:

  $ g++ -march=rv64imfd -std=c++11 -nostdlib libcxx-atomic-check.cpp 
  /usr/lib/gcc/riscv64-unknown-linux-gnu/9.1.0/../../../../riscv64-unknown-linux-gnu/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000000310
  /usr/lib/gcc/riscv64-unknown-linux-gnu/9.1.0/../../../../riscv64-unknown-linux-gnu/bin/ld: /tmp/ccNebYb9.o: in function `.L0 ':
  libcxx-atomic-check.cpp:(.text._ZNSt13__atomic_baseImEpLEm[_ZNSt13__atomic_baseImEpLEm]+0x28): undefined reference to `__atomic_fetch_add_8'
  collect2: error: ld returned 1 exit status

I think it needs to be fixed as well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D68964/new/

https://reviews.llvm.org/D68964





More information about the llvm-commits mailing list