1

我有一个用于 Android 的本机库,其中包含一些包含 NEON 汇编代码的文件。我从其他一些编码员那里继承了这段代码,并且至少可以说,鉴于我对 NEON 程序集编码(或任何程序集,就此而言)的了解是轻薄的。无论如何,我注意到以下问题:当我使用 'ndk-build NDK_DEBUG=1' 编译时,一切都很好。当我编译发布时,'ndk-build NDK_DEBUG=0',编译器优化掉汇编代码。我已经设法通过破解 ndk 构建脚本并将我的库分成两部分来解决这个问题,其中一个库包含所有的程序集文件 - 对于这个库,我以一种非常 hacky 的方式将优化设置为“-O0” . 所以问题是:如何为特定文件指定优化级别?在 Application.mk 中设置 APP_OPTIM,这会影响所有编译的文件。NDK_DEBUG 标志也是如此。

编辑:根据 Alex 的要求,这是我最终使用的 Android.mk,将 lib 分成两部分:一部分带有汇编代码(和 -O0),另一部分带有常规 C 代码(和 -O2):

LOCAL_PATH := $(call my-dir)

# assembly_neon_code_here (neon) module - turn optimization off
include $(CLEAR_VARS)

LOCAL_MODULE := assembly_neon_code_here
LOCAL_SRC_FILES := assembly_neon_code_here.cpp
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

LOCAL_CFLAGS := -O0
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 
include $(BUILD_SHARED_LIBRARY)

# main module
include $(CLEAR_VARS)

LOCAL_MODULE    := complete_lib
LOCAL_SRC_FILES := regular_src1.cpp regular_src2.cpp regular_src3.cpp 
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_ARM_NEON := true
endif

# allow logcat calls
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
LOCAL_SHARED_LIBRARIES := assembly_neon_code_here
include $(BUILD_SHARED_LIBRARY)
4

2 回答 2

3

GCC >= 4.4 似乎支持#pragma GCC optimize更改优化级别的中间文件,并且还可以为optimize每个函数设置它。

请参阅http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Function-Specific-Option-Pragmas.html#Function-Specific-Option-Pragmashttp://gcc.gnu.org/onlinedocs /gcc-4.4.7/gcc/Function-Attributes.html#Function-Attributes

根据这些链接,将#pragma GCC optimize ("O0")导致问题的文件放在顶部应该可以解决问题。

于 2012-10-02T17:27:38.603 回答
1

我不知道如何更改每个文件的优化级别,但这样做可能会损害您的应用程序的性能,所以我不推荐它。我假设汇编代码是内联汇编块的形式,即汇编代码块与普通的 C 或 C++ 代码交错。它看起来如下

asm {
  .. assembly goes here, usually each line in double-quotes, often ending in \n\t
  : ... input operands. Might not be present ...
  : ... output operands. Might not be present ...
  : ... clobber operands. Might not be present ...
}

编译器删除内联汇编块的最可能原因是它不包含输出操作数,或者输出操作数全部未使用。您可以通过将内联汇编块标记为volatile告诉编译器不要弄乱它来避免尝试。为此,只需volatileasm关键字后面写。

阻止编译器弄乱内联汇编块的另一件事是将“内存”添加到他们的clobber列表中。这告诉编译器程序集正在读取或写入任意内存位置。当您使用它时,还要添加“cc”以获得良好的效果。这告诉编译器内联汇编与条件代码寄存器混淆,即它执行的测试指令会影响后面的条件分支指令的行为。

总之,尝试使所有内联汇编块看起来像这样

asm volatile {
  .. whatever ...
  : ... whatever ...
  : ... whatever ...
  : ... whatever ..., "cc", "memory"
}

注意,asm也可能是拼写__asm__,thatvolatile也可能是拼写__volatile__

于 2012-09-30T21:53:53.847 回答