gcc -O0仍然优化出“未使用"的状态.代码.是否有一个编译标志来改变它? [英] gcc -O0 still optimizes out "unused" code. Is there a compile flag to change that?

查看:174
本文介绍了gcc -O0仍然优化出“未使用"的状态.代码.是否有一个编译标志来改变它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我提出这个问题时,gcc正在删除(是的,使用-O0)一行代码_mm_div_ss(s1, s2);可能是因为未保存结果.但是,此应该会触发浮点异常并引发SIGFPE,如果删除该调用,则不会发生.

As I brought up in this question, gcc is removing (yes, with -O0) a line of code _mm_div_ss(s1, s2); presumably because the result is not saved. However, this should trigger a floating point exception and raise SIGFPE, which can't happen if the call is removed.

问题:是否有一个或多个标志传递给gcc,以便按原样编译代码?我在想类似fno-remove-unused的东西,但我没有看到类似的东西.理想情况下,这将是一个编译器标志,而不必更改我的源代码,但是如果不支持,则可以使用一些gcc属性/编译指示来代替?

Question: Is there a flag, or multiple flags, to pass to gcc so that code is compiled as-is? I'm thinking something like fno-remove-unused but I'm not seeing anything like that. Ideally this would be a compiler flag instead of having to change my source code, but if that isn't supported is there some gcc attribute/pragma to use instead?

我尝试过的事情:

$ gcc --help=optimizers | grep -i remove

没有结果.

$ gcc --help=optimizers | grep -i unused

没有结果.

并显式禁用所有无效代码/消除标志-请注意,没有关于未使用代码的警告:

And explicitly disabling all dead code/elimination flags -- note that there is no warning about unused code:

$ gcc -O0 -msse2 -Wall -Wextra -pedantic -Winline \
     -fno-dce -fno-dse -fno-tree-dce \
     -fno-tree-dse -fno-tree-fre -fno-compare-elim -fno-gcse  \
     -fno-gcse-after-reload -fno-gcse-las -fno-rerun-cse-after-loop \
     -fno-tree-builtin-call-dce -fno-tree-cselim a.c
a.c: In function ‘main’:
a.c:25:5: warning: ISO C90 forbids mixed declarations and code [-Wpedantic]
     __m128 s1, s2;
     ^
$


源程序


Source program

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <xmmintrin.h>

static void sigaction_sfpe(int signal, siginfo_t *si, void *arg)
{
    printf("%d,%d,%d\n", signal, si!=NULL?1:0, arg!=NULL?1:0);
    printf("inside SIGFPE handler\nexit now.\n");
    exit(1);
}

int main()
{
    struct sigaction sa;

    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_sigaction = sigaction_sfpe;
    sa.sa_flags = SA_SIGINFO;
    sigaction(SIGFPE, &sa, NULL);

    _mm_setcsr(0x00001D80);

    __m128 s1, s2;
    s1 = _mm_set_ps(1.0, 1.0, 1.0, 1.0);
    s2 = _mm_set_ps(0.0, 0.0, 0.0, 0.0);
    _mm_div_ss(s1, s2);

    printf("done (no error).\n");

    return 0;
}

编译上面的程序会得到

$ ./a.out
done (no error).

更改线路

_mm_div_ss(s1, s2);

s2 = _mm_div_ss(s1, s2); // add "s2 = "

产生预期的结果:

$ ./a.out
inside SIGFPE handler


编辑更多详细信息.


Edit with more details.

这似乎与_mm_div_ss __always_inline__属性有关. h#L145"rel =" nofollow noreferrer>定义.

This appears to be related to the __always_inline__ attribute on the _mm_div_ss definition.

$ cat t.c
int
div(int b)
{
    return 1/b;
}

int main()
{
    div(0);
    return 0;
}


$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
$  

(无警告或错误)

$ ./t.out
Floating point exception
$

vs下方(函数属性相同)

vs below (same except for function attributes)

$ cat t.c
__inline int __attribute__((__always_inline__))
div(int b)
{
    return 1/b;
}

int main()
{
    div(0);
    return 0;
}

$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
$   

(无警告或错误)

$ ./t.out
$

添加功能属性__warn_unused_result__至少会给出一条有用的消息:

Adding the function attribute __warn_unused_result__ at least gives a helpful message:

$ gcc -O0 -Wall -Wextra -pedantic -Winline t.c -o t.out
t.c: In function ‘main’:
t.c:9:5: warning: ignoring return value of ‘div’, declared with attribute warn_unused_result [-Wunused-result]
     div(0);
     ^

gcc邮件列表上的一些讨论.最终,我认为一切都按预期进行.

Some discussion on the gcc mailing list. Ultimately, I think everything is working as intended.

推荐答案

GCC此处未优化"任何内容.它只是不会生成无用的代码.似乎很普遍的幻想是,编译器应该生成某种纯粹的代码形式,而对其进行的任何更改都是优化".没有这样的东西.

GCC doesn't "optimize out" anything here. It just doesn't generate useless code. It seems to a very common illusion that there's some pure form of code that the compiler should generate and any changes to that are an "optimization". There is no such thing.

编译器创建一些表示代码含义的数据结构,然后在该数据结构上进行一些转换,并从中生成汇编程序,然后将该汇编程序编译为指令.如果您在没有优化"的情况下进行编译,则仅意味着编译器将尽最大的努力来生成代码.

The compiler creates some data structure that represents what the code means, then it applies some transformations on that data structure and from that it generates assembler that then gets compiled down to instructions. If you compile without "optimizations" it just means that the compiler will only do the least effort possible to generate code.

在这种情况下,整个语句是无用的,因为它不执行任何操作并立即被丢弃(在扩展内联函数和内建函数的含义之后,它等同于编写a/b;,不同之处在于,编写会发出有关statement with no effect的警告,而内建函数可能不会由相同的警告处理).这不是一种优化,编译器实际上将不得不付出更多的努力来将意义发明为无意义的语句,然后伪造一个临时变量来存储该语句的结果,然后将其丢弃.

In this case, the whole statement is useless because it doesn't do anything and is thrown away immediately (after expanding the inlines and what the builtins mean it is equivalent to writing a/b;, the difference is that writing a/b; will emit a warning about statement with no effect while the builtins probably aren't handled by the same warnings). This is not an optimization, the compiler would actually have to expend extra effort to invent meaning to a meaningless statement, then fake a temporary variable to store the result of this statement to then throw it away.

您要查找的不是禁用优化的标志,而是悲观标志.我认为没有任何编译器开发人员会浪费时间实施此类标志.除了可能是愚人节的玩笑.

What you're looking for is not flags to disable optimizations, but pessimization flags. I don't think any compiler developers waste time implementing such flags. Other than maybe as an April fools joke.

这篇关于gcc -O0仍然优化出“未使用"的状态.代码.是否有一个编译标志来改变它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆