8

I've been trying to read through the MSDN pages on the various optimization flags.

We currently have most of our projects set to /O2 which optimizes for "maximize speed".

My confusion is what exactly this means. Which of the following statements are closer to true regarding the /O2 flag?

  1. Optimize the code for both speed and size, but if there is contention prefer optimization for speed
  2. Optimize the code only for speed, do not optimize for size.

I made the argument that we should use the /Ox flag, but that was when I was under the impression that Option 2 was true.

I was basically told "we're not going to change from /O2 to /Ox unless someone has solid evidence that we need to do so".

So my question is does /O2 still perform memory optimizations? E.g. return value optimization, copy elision, etc. What would we gain from switching from /O2 to /Ox?

VAndrei
  • 5,420
  • 18
  • 43
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218

3 Answers3

9

As Arkanosis pointed out correctly, when going from /O2 to /Ox, you disable /Gs, /GF, /Gy. The question is which of these flags may increase execution speed?

/Gs is identical to /Gs0 and can have negative impact on performance. See below the description on MSDN.

activates stack probes for every function call that requires storage for local variables. This can have a negative impact on performance

/GF eliminates duplicate strings (constants) - called string pooling. This will reduce the code size. A lower code could produce lower number of instruction cache misses but I doubt this effect is observable on most codes.

/Gy flag alows packaging individual functions into COMDAT structures. These can be used as a workaround to avoid compile time errors due to multiple definitions of the same symbol. The MSDN documentation states that this just affects build time but not the execution time. They generally recommend using it.

Conclusion:

/Ox disables /Gs, /GF, /Gy. In some cases, these options hurt performance and almost never improve execution speed, compared with /O2. Of course they have benefits but not related to speed.

VAndrei
  • 5,420
  • 18
  • 43
  • `/Gy` by itself doesn't improve run-time performance, but the `/OPT:REF` linker option might (it certainly decreases file size, especially when you're linking with a static library), and it requires `/Gy`. I've also never seen anyone debate whether string pooling's reduction in code size is a benefit. Certainly there is no *harm* in consolidating duplicate strings. – Cody Gray - on strike Jun 07 '16 at 10:38
  • 2
    "and almost never they don't improve execution speed" - This portion is a bit confusing. Did you mean "and they almost never improve execution speed"? – Marc.2377 Jul 29 '16 at 18:06
6
  • /02 is the same as /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy
  • /Ox is the same as /Og /Oi /Ot /Oy /Ob2

So switching from /O2 to /Ox means:

  • no /Gs (no controls stack probes)
  • no /GF (no string pooling)
  • no /Gy (no function-level linking)
Arkanosis
  • 2,229
  • 1
  • 12
  • 18
0

So my question is does /O2 still perform memory optimizations?

Depends what you mean by memory optimization.

/O1 is guaranteed to optimize the code based on binary size.

Creates the smallest code in the majority of cases.

/O2 primarily aims to optimize code for faster speed.

Creates the fastest code in the majority of cases. (default setting for release builds)

Cases when /O2 is orthogonal to /O1 (not limited) when

  • compiler does loop unrolling,
  • code reordering
  • code inlining

Now consider /Ox, it produces code that favors execution speed over smaller size, so /Ox does not includes /Os (Favor Small Code) minimizes the size of EXEs and DLLs by instructing the compiler to favor size over speed.

Abhijit
  • 62,056
  • 18
  • 131
  • 204