微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

_Pragma GCC在宏中进行优化后,GCC CLI选项-O0令人惊讶地丢弃了代码

如何解决_Pragma GCC在宏中进行优化后,GCC CLI选项-O0令人惊讶地丢弃了代码

今天,我在GCC上发现了一个奇怪的怪癖,这让我感到惊讶,我无法解释。

我们的项目设置使用-O0作为GCC的命令行选项,我对此不太满意,因为这不会执行很多恒定的折叠操作,并且会产生不必要的寄存器和堆栈使用,从而影响嵌入式系统的性能。但是,我的问题似乎是最新的,而不是IDE特定的编译器版本的问题,因为我首先在godbolt.org上发现了具有最新可用32位ARM GCC的问题。

这是我原来的宏:

#define _STRING(S) #S
#define STRING(S) _STRING(S)
#define OPTIMIZE(OLEVEL,...)\
_Pragma("GCC push_options")\
_Pragma(STRING(GCC optimize ("O" #OLEVEL)))\
__VA_ARGS__\
_Pragma("GCC pop_options")

我创建了这个宏,以使用优化Pragmas包含代码(顶层函数)。现在奇怪的是:当宏中未包含该函数但我用等效的宏替换了文字代码时,它编译了该函数,并且编译中省略了该代码。最后,我来到这个例子:

#define OPTIMIZE \

_Pragma("GCC push_options")\
_Pragma(STRING(GCC optimize ("O2")))\
    int square(int num) {\
        return num * num;\
    }\
_Pragma("GCC pop_options")

OPTIMIZE

这将完美地工作!但是现在,如果您删除定义和代码间的空行以将代码放入定义中,那么尽管它们是相同的代码,但所有代码都将被省略!您可以使用ARM GCC 8.2在godbolt.org上对其进行测试,这使我一无所知,因为如果您选择与宏中的pragma选项相关的CLI优化选项(例如,如果OLEVEL的-Ox,x> 0,则不会发生此问题)是x> 0;如果OLEVEL为0,则为-O0;如果OLEVEL为快速,则为-Ofast ...)。

在#define-macro内,我试图在函数与上面的GCC优化_Pragma之间放置不同类型的行,代码和分号,但没有任何帮助。用_STRING替换STRING或引入宏参数或从_Pragma中删除OLEVEL都无济于事。唯一有帮助的是通过优化_Pragma从宏中排除代码

这也不起作用:

#define START_OPTIMIZE(OLEVEL)\
_Pragma("GCC push_options")\
_Pragma(STRING(GCC optimize ("O" #OLEVEL)))
#define END_OPTIMIZE _Pragma("GCC pop_options")
#define OPTIMIZE(OLEVEL,...) \
START_OPTIMIZE(OLEVEL)\
__VA_ARGS__\
END_OPTIMIZE

在宏中将 VA_ARGS 行与END_OPTIMIZE交换也不会!

的另一层间接
#define SPREAD(FUNC,...) FUNC(__VA_ARGS__)

没有帮助。我太着急了,无法进一步尝试。

我想出并起作用的解决方案是:

#define OPTIMIZE(OLEVEL)\
_Pragma("GCC push_options")\
_Pragma(STRING(GCC optimize ("O" #OLEVEL)))
#define END_OPTIMIZE _Pragma("GCC pop_options")
...
OPTIMIZE(2)
int square(int num) {
    return num * num;
}
END_OPTIMIZE

但是我真的很想知道这个问题,因为在我的项目部分这是一个非常严重的问题,因为我用过度优化杀死了它,并且需要划定优化范围。有意吗可以解决吗?

谢谢。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。