Search code examples
androidgccandroid-ndkneon

Errors when compiling NEON code on Android


Here is simple binarization function

void binarize(void *output, const void *input, int begin, int end, uint8_t threshold) {
#ifdef __ARM_NEON__
    uint8x16_t thresholdVector = vdupq_n_u8(threshold);
    uint8x16_t highValueVector = vdupq_n_u8(255);
    uint8x16_t* __restrict inputVector = (uint8x16_t*)input;
    uint8x16_t* __restrict outputVector = (uint8x16_t*)output;
    for ( ; begin < end; begin += 16, ++inputVector, ++outputVector) {
        *outputVector = (*inputVector > thresholdVector) & highValueVector;
    }
#endif
}

It works fine on iOS. However when I'm compiling it for Android it gives me an error:

error: invalid operands of types 'uint8x16_t {aka __vector(16) __builtin_neon_uqi}' and 'uint8x16_t {aka __vector(16) __builtin_neon_uqi}' to binary 'operator>'

I use this flag in Android.mk to enable NEON:

ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
      LOCAL_ARM_NEON := true
endif

Solution

  • The difference comes because of different compilers. For iOS you are compiling with Clang but for Android you are building the code with GCC (unless you override the defaults).

    GCC is much more stupid about vector types and could not use them with C/C++ operators like > or &. So you have two basic options:

    1. Try to compile with Clang from the latest Android NDK r8c

      Put NDK_TOOLCHAIN_VERSION=clang3.1 to your Application.mk for this.

    2. Rewrite your code explicitly using vld1q_u8 for load, vst1q_u8 for store, vcgtq_u8 for operator > and vandq_u8 for operator &