gcc/clang 优化时 de-/serializaing

gcc/clang optimization when de-/serializaing

一些 gcc/clang 编译器优化允许重新排序程序集中代码的执行(例如,对于 gcc:-freorder-blocks -freorder-blocks-and-partition -freorder-functions)。当 de-/serializing 特定顺序的数据结构时使用此类优化是否安全?

例如:

void write(int* data,std::ofstream& outstream)
{
  outstream.write(reinterpret_cast<char*>(data),sizeof(int));
}

void read(int* data,std::ifstream& instream)
{
  instream.read(reinterpret_cast<char*>(data),sizeof(int));
}

void serialize()
{
  std::ofstream ofs("/somePath/to/some.file");
  int i = 1;
  int j = 2;
  int k = 3;

  write(i, ofs);
  write(j, ofs);
  write(k, ofs);

  ofs.close();
}

void deserialize()
{
  std::ifstream ifs("/somePath/to/some.file");
  int i;
  int j;
  int k;

  read(i, ifs);
  read(j, ifs);
  read(k, ifs);

  ifs.close();
}

-freorder-blocks-freorder-blocks-and-partition-freorder-functions 都会影响代码在可执行文件中的布局顺序:

  • -freorder-blocks 允许 gcc 重新排列汇编代码的直线块,这些代码块组合在一起形成您的函数,以尝试最小化您的 CPU 的分支预测未命中数可能会让。

  • -freorder-functions 获取编译器认为不太可能执行的函数并将它们移动到可执行文件的较远部分。这样做的目的是尝试将尽可能多的频繁执行的代码打包到尽可能少的内存中,以便尽可能多地从指令缓存中受益。

  • -freorder-blocks-and-partition 类似于 -freorder-functions,但在汇编块级别。如果您的代码中有一个 if (unlikely(foo)) { x = 1; } 分支,那么编译器可能会选择代表 x = 1; 的代码并将其移出经常执行的代码。

其中

None 会影响程序的控制流。所有优化都将保证,如果您将 i 写入文件,然后将 j 写入文件,那么在应用优化后仍然会观察到。