如何更改一个函数的优化级别?

时间:2015-07-13 00:21:09

标签: c gcc optimization pragma

这与Determine cause of segfault when using -O3?有关在这个问题中,我使用特定版本的GCC在使用-O3编译时捕获特定函数中的段错误。在-O3处,使用了矢量化指令(在-O2,不使用它们。)

我想在较低的优化级别中包装单个函数。根据{{​​3}},我可以做到。但是,按照问题和答案中的各种链接,我找不到"答案的答案,确切地说,#34;

如何将单个函数标记为使用不同的优化级别?

相关,我不想将此函数移动到单独的文件,然后为它提供不同的makefile配方。这样做会打开另一种蠕虫,就像在某些平台上将它应用于GCC 4.9一样。

3 个答案:

答案 0 :(得分:12)

我知道这个问题被标记为海湾合作委员会,但我只是looking into doing this portably并认为结果可能对某人有用,所以:

  • GCC具有optimize(X)功能属性
  • Clang具有optnoneminsize个函数属性(使用__has_attribute来测试支持)。由于我相信 3.5,它也有#pragma clang optimize on|off
  • 英特尔C / C ++编译器#pragma intel optimization_level 0适用于pragma之后的下一个函数
  • MSVC有#pragma optimize,适用于pragma之后的第一个函数
  • IBM XL#pragma option_override(funcname, "opt(level,X)")。请注意,对于__has_attribute(optnone),13.1.6(至少)返回true,但实际上并不支持它。
  • ARM有#pragma Onum,可以与#pragma push/pop
  • 结合使用
  • ODS#pragma opt X (funcname)
  • Cray#pragma _CRI [no]opt
  • TI#pragma FUNCTION_OPTIONS(func,"…")(C)和#pragma FUNCTION_OPTIONS("…")(C ++)
  • IAR#pragma optimize=...
  • Pelles C有#pragma optimize time/size/none

因此,对于GCC / ICC / MSVC / clang / IAR / Pelles和TI C ++,您可以定义一个刚刚放在函数之前的宏。如果要支持XL,ODS和TI C,可以添加函数名作为参数。在函数弹出设置后,ARM将需要另一个宏。对于Cray AFAIK,您无法恢复之前的值,只能关闭和打开优化。

我认为这样做的主要原因是禁用对错误编译器(或编译器中暴露代码中的错误)的优化,因此统一的可移植体验可能并不重要,但希望此列表可以帮助找到合适的人他们的编译器的解决方案。

编辑:值得注意的是,禁用优化是相对常见的,因为之前不再有效的代码。虽然编译器中可能存在错误,但您的代码更可能依赖于未定义的行为,而更新,更智能的编译器可以并且将忽略未定义的情况。在这种情况下正确的答案不是禁用优化,而是修复代码。关于clang和gcc的UBsan可以在这里提供很多帮助;使用-fsanitize=undefined进行编译,许多未定义的行为将在运行时开始发出警告。此外,尝试使用您可以启用的所有警告选项进行编译;对于GCC来说意味着-Wall -Wextra,对于-Weverything中的铿锵声。

答案 1 :(得分:8)

https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes

中描述了它

您可以通过声明如下函数来更改级别:

void some_func() __attribute__ ((optimize(1))) {
    ....
}

强制优化级别1.

答案 2 :(得分:3)

以下是如何使用pragma:

#pragma GCC push_options
#pragma GCC optimize ("-O2")
void xorbuf(byte *buf, const byte *mask, size_t count)
{
   ...
}
#pragma GCC pop_options

使其便携,如下所示。

#define GCC_OPTIMIZE_AWARE (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)

#if GCC_OPTIMIZE_AWARE
# pragma GCC push_options
# pragma GCC optimize ("-O2")
#endif

它需要被包装,因为使用-Wall,旧版本的GCC不理解-Wno-unknown-pragma,并且它们将导致编译嘈杂。将在现场遇到旧版本,如OpenBSD上的GCC 4.2.1。

但根据Markus Trippelsdorf在GCC邮件列表When did 'pragma optimize' become available?上的说法:

  

总的来说这是一个坏主意,因为“pragma GCC优化”的意思是   仅限编译器调试辅助工具。它应该在生产中使用   码。