c – 这是g中的优化错误吗?

前端之家收集整理的这篇文章主要介绍了c – 这是g中的优化错误吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我不确定我是否在g(4.4.1-4ubuntu9)中发现了一个错误,或者我是否正在做
有问题.我相信我所看到的是启用引入的错误
使用g -O2进行优化.我试图将代码提炼到只有
相关部分.

启用优化后,我有一个失败的ASSERT.什么时候
优化被禁用,相同的ASSERT不会失败.我想我已经跟踪了
它归结为一个函数及其调用者的优化.

系统

>语言:C
> Ubuntu 9.10
> g -4.4.real(Ubuntu 4.4.1-4ubuntu9)4.4.1
> Linux 2.6.31-22-server x86_64

优化已启用

编译对象:
g -DHAVE_CONFIG_H -I. -fPIC -g -O2 -MT file.o -MD -MP -MF .deps / file.Tpo -c -o file.o file.cpp

这是来自objdump -dg file.o的相关代码.

00000000000018b0 

优化已禁用

现编译:
g -DHAVE_CONFIG_H -I. -fPIC -g -O0 -MT file.o -MD -MP -MF .deps / file.Tpo -c -o file.o file.cpp

0000000000008d27 

原始C代码

这是原始C的消毒版本.我刚刚更改了一些名字
删除了不相关的代码.原谅我的偏执,我只是不想暴露
来自未发表和未发布的工作的代码太多:-).

static void helper_function(my_struct_t *e,int *outArr)
{
  unsigned char event_type = e->header.type;
  if (event_type == event_A || event_type == event_B) {
    outArr[0] = action_one;
  } else if (event_type == event_C) {
    outArr[0] = action_one;
    outArr[1] = action_two;
  } else if (...) { ... }
}

static void buggy_invoker(my_struct_t *e,predicate_t pred)
{
  // MAX_ACTIONS is #defined to 5
  int action_array[MAX_ACTIONS] = {0};
  helper_function(e,action_array);
  ...
}

static int has_any_actions(my_struct_t *e)
{
  int actions[MAX_ACTIONS] = {0};
  helper_function(e,actions);
  return actions[0] != 0;
}

// *** ENTRY POINT to this code is this function (note not static).
void perfectly_fine_invoker(my_struct_t e,predicate_t pred)
{
  memfence();
  if (has_any_actions(&e)) {
    buggy_invoker(&e,pred);
  }
  ...
}

如果您认为我已经过度混淆或消除了太多,请告诉我.用户
这段代码叫’perfect_fine_invoker’.通过优化,g优化了
‘has_any_actions’函数可直接调用’helper_function’,即
你可以在装配中看到.

问题

所以,我的问题是,对任何人来说,它看起来像一个错误的优化吗?

如果它有用,我可以发布原始C代码的消毒版本.

这是我第一次发布Stack Overflow,所以如果我能做的话请告诉我
任何使问题更清晰或提供任何其他信息的事情.

答案

编辑(事后几天):

我在下面接受了我的问题的答案 – 这不是g中的优化错误,我只是看错了汇编代码.

但是,对于将来可能会看到这个问题的人,我找到了答案.我在C(http://blog.regehr.org/archives/213http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html)中对未定义的行为进行了一些阅读,并且编译器的一些描述使用未定义的行为优化掉函数似乎非常熟悉.

我在函数’helper_function’中添加了一些NULL指针检查,并且看到…… bug消失了.我应该开始使用NULL指针检查,但显然没有让它们允许g做任何想做的事情(在我的情况下,优化掉调用).

希望这些信息有助于未来的人.

最佳答案
我觉得你在看错了.我想编译器注意到你的函数很短并且没有触及%rdi寄存器所以它只是不管它(你有与第一个参数相同的变量,我想这是放在%rdi中的内容.参见第21页这里http://www.x86-64.org/documentation/abi.pdf)

如果查看未优化的版本,它会在此行保存%rdi寄存器

9498:       48 89 bd 38 fe ff ff    mov    %rdi,-0x1c8(%rbp)

…然后在调用helper_function之前,它将保存的值移动到移动到%rdi的%rax中.

94c1:       48 8b 85 38 fe ff ff    mov    -0x1c8(%rbp),%rax
94c8:       48 89 d6                mov    %rdx,%rsi
94cb:       48 89 c7                mov    %rax,%rdi

在优化它时,编译器就可以摆脱所有来回移动.

猜你在找的Linux相关文章