Search code examples
gccserializationclangcompiler-optimizationllvm-clang

gcc/clang optimization when de-/serializaing


Some gcc/clang compiler optimizations allow reordering the execution of code in the assembly (e.g. for gcc: -freorder-blocks -freorder-blocks-and-partition -freorder-functions). Is it safe to use such optimizations when de-/serializing data structures in a specific order?

For instance:

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();
}

Solution

  • -freorder-blocks, -freorder-blocks-and-partition, and -freorder-functions all influence the order in which code is laid out in your executable file:

    • -freorder-blocks allows gcc to rearrange the straight-line blocks of assembly code that combine to form your function to try and minimize the number of branch prediction misses that your CPU might make.

    • -freorder-functions takes the functions that the compiler deems unlikely to execute and moving them to a far away part of your executable file. The goal of doing so is to try and pack as much frequently-executed code into as little memory as possible so as to benefit from the instruction cache as much as possible.

    • -freorder-blocks-and-partition is like -freorder-functions, but at the assembly block level. If you have an if (unlikely(foo)) { x = 1; } branch in your code, then the compiler might choose to take the code representing x = 1; and move it away frequently executed code.

    None of these will affect the control flow of your program. All optimizations will guarantee that if you write i to a file and then j to a file, then that will still be what is observed after optimizations are applied.