Quick Tips On Using Whole Program Optimization

Hi, I’m Jerry Goodwin from the Visual C++ code generation and optimization team, with a couple quick tips on using Whole Program Optimization, also referred to as Link Time Code Generation (LTCG).


If you’re writing native C++ code, you can typically speed up your optimized code by about another 3-4% by adding the /GL flag to your compiles.  This flag tells the compiler to defer code generation until you link your program. Then at link time the linker calls back to the compiler to finish compilation. If you compile all your sources this way, the compiler optimizes your program as a whole rather than one source file at a time. For users building with the IDE, this option is found under the C/C++ optimization settings, and is already on by default for retail builds in new projects.


Using Whole Program Optimization provides the optimizer with a number of extra optimization opportunities, but I’ll give just one example. Many people are already familiar with the benefits of inlining a called function into the caller. We can only do inlining when we are generating code for both the calling function and the called function at the same time. With Link Time Code Gen we can inline functions from one source file into callers defined in another source file, as long as both source files were compiled with /GL.


If you do use /GL, here are four caveats to keep in mind:


1.       When building from the command line or via makefiles, you need to add the /LTCG switch to the link command line to tell the linker to expect to see one or more object files that were compiled with /GL. If you don’t, some build time will be wasted because the linker will have to start over when it gets to the module compiled with /GL. If you build through the IDE this is in your project configuration settings on the Linker optimization page.

2.       Using /GL reduces your compile times, but your link time will increase, because work is being moved to during the link. Overall build time might increase a little, but shouldn’t increase a lot.

3.       Don’t compile managed code with /GL. Link time code gen provides little or no benefit to managed code, and this option combination (/GL /clr) is being removed in the next compiler release, so you can future-proof your build by using link time code generation only for native code. If you’re building managed code using the IDE, the default setting is to use /GL in release builds, and I recommend you disable it for managed code. For mixed managed and native code, compiling only the native code with /GL and linking with /LTCG gives best results.

4.       Never use /GL for code you intend to put in a library and ship to your customers. Doing so means that your customers will be doing the code gen for your library when they link their application. Since some of your customers could have different versions of the compiler, shipping a lib built this way could cause various maintenance problems for you. If your customer’s compiler is from a prior release, their link may fail. If their version is newer than yours, the code they generate won’t be exactly equal to what you’ve tested, and could behave differently for them than when you tested it. In VS 2008, the IDE default for the class library template release configuration is to build using /GL, and I strongly encourage everyone to reset that.


Here are links for more information on this topic:


The /GL compiler switch (http://msdn.microsoft.com/en-us/library/0zza0de8.aspx)

            The /LTCG linker switch (http://msdn.microsoft.com/en-us/library/xbf3tbeh.aspx)

            A detailed article about Link Time Code Generation (http://msdn.microsoft.com/en-us/magazine/cc301698.aspx)