2

在下面的程序中,out变量总是打印出来,就0好像它是用上面的优化编译的一样O1。如果我取消注释函数中的行,则该out变量会以任何级别的优化正确打印。coutdigitTruncate

我是在做“未定义”的事情,还是编译器问题?

#include <iostream>
#include "mytime.hpp"
#include <stdint.h>

template <class IN>
int32_t
digitTruncate (IN data_in, uint32_t digits, uint64_t* data_out,
               int32_t bits = -1, bool safe = false)
{
  if (bits == -1)
    bits = (digits / 0.3010299957) + 1;
  if (!safe) 
  {
    if (bits > (int32_t)sizeof(data_in) * 8)
      return -1;
  }
  *data_out = (data_in & (0xffffffffffffffff >> (64 - bits)));
  //std::cout << *data_out << std::endl;
  return (bits / 8) + 1;
}

int
main()
{
  uint64_t cycles1, cycles2;
  uint32_t out;
  char* block = new char[8];
  cycles1 = mytime::cycles();
  for (int i = 0; i < 10000; i++)
  {
    uint32_t init = (uint32_t)mytime::cycles();
    digitTruncate(init, 5, ((uint64_t*)block), 17, true);
    out = *((uint32_t*)block);
  }
  cycles2 = mytime::cycles();
  std::cout << cycles2 - cycles1 << std::endl;
  std::cout << "results: " << out << std::endl;

  return 0;
}
4

2 回答 2

3

通过block作为指向两者的指针访问uint64_tuint32_t您违反了严格的别名规则。允许编译器假设特定地址仅作为char*另一种类型访问(别名)。您正在使用两种非char*类型,因此对于编译器的优化器会做什么,所有的赌注都没有了。

于 2013-04-30T04:53:13.843 回答
1

由于循环中的值是死的,除了最后一次迭代,并且函数除了设置(因此)out之外没有副作用,编译器可以自由地消除循环,只计算最后一次迭代。上次迭代的大部分代码也可以不断折叠。blockout

所以你最终只连续两次调用mytime::cycles(),这可能会有 0 的差异......

编译器可能首先内联调用,然后将其简化为无,而不是注意到它实际上并没有做任何事情,但总体效果是一样的。

于 2013-04-30T03:42:59.800 回答