Skip to content

NEON64 code link error if gcc -O1 or -O0 #573

Closed

Description

@cyb70289

A simple test code

#include <cstddef>
#include <xsimd/xsimd.hpp>

int main() {
  using simd_batch = xsimd::batch<int8_t, xsimd::neon64>;

  simd_batch a(1);
  simd_batch b(2);
  simd_batch c = a | b;

  return xsimd::any(b < c);
}

Compile with gcc -O1 or -O0

$ g++ -O1 neon-debug.cc  -I./include -march=armv8-a -std=c++11

/tmp/cc89XtTV.o: In function `main':
neon-debug.cc:(.text+0x10): undefined reference to `vorrq_s8(__Int8x16_t, __Int8x16_t)'
neon-debug.cc:(.text+0x1c): undefined reference to `vcltq_s8(__Int8x16_t, __Int8x16_t)'
collect2: error: ld returned 1 exit status

Other info

Activity

  1. cyb70289 commented on Sep 29, 2021

    @cyb70289
    ContributorAuthor

    Looks the error is from below static dispatcher code:
    https://github.com/xtensor-stack/xsimd/blob/master/include/xsimd/arch/xsimd_neon.hpp#L42-L44

    Without optimization, gcc treats the returned neon func (vorrq_s8, ...) as a function pointer, and tries to find the function at link time, which causes the error.

    From this example code: https://godbolt.org/z/orsqz7xTn, obviously gcc thinks vorrq_s8 is a function implemented somewhere.

  2. cyb70289 commented on Sep 29, 2021

    @cyb70289
    ContributorAuthor

    @JohanMabille @serge-sans-paille do you have ideas how to address this issue?

  3. serge-sans-paille commented on Sep 29, 2021

    @serge-sans-paille
    Contributor

    @cyb70289 can you try flagging the function as __attribute__((always_inline)) ?

  4. cyb70289 commented on Sep 29, 2021

    @cyb70289
    ContributorAuthor

    @cyb70289 can you try flagging the function as __attribute__((always_inline)) ?

    Flagging this function as always_inline? I tried but it doesn't help.
    __attribute__((always_inline)) inline return_type<U> apply(U lhs, U rhs) const

  5. cyb70289 commented on Sep 29, 2021

    @cyb70289
    ContributorAuthor

    I filed a gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102526

    As a workaround, I think xsimd users (e.g., apache arrow) can bypass simd code for gcc debug build on aarch64. This should be acceptable as you don't care about performance for debug build.

  6. cyb70289 commented on Sep 30, 2021

    @cyb70289
    ContributorAuthor

    Gcc community does not think it's a bug, there was a discussion: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100005
    I'm inclined to agree with the community. Taking address of an intrinsic does looks a bit strange.

    One approach to fix this issue is to wrap the intrinsic with a lambda, which gives a pseudo address
    to intrinics. See below example.
    Current code:

    constexpr neon_dispatcher::binary dispatcher =
    {
        std::make_tuple(vorrq_u8, vorrq_s8, .......)
    };
    

    Updated code:

    //  cannot use constexpr here, consexpr lambda is c++17 feature
    const neon_dispatcher::binary dispatcher =
    {
        // of course, we need better wrapper to simplify the code
        std::make_tuple([](uint8x16_t a, uint8x16_t b){ return vorrq_u8(a,b); }, .......)
    };
    

    I've tested this method works okay with -O0, and incurs no penalty with higher optimization levels.
    What's your opinion? @serge-sans-paille @JohanMabille
    If you think it's okay, I'm glad to upload a PR.

  7. serge-sans-paille commented on Sep 30, 2021

    @serge-sans-paille
    Contributor
  8. added a commit that references this issue on Oct 11, 2021
    f212f3c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions