MSVC Backend Updates in Visual Studio 2019 version 16.2

Daniel Donenfeld

In Visual Studio 2019 version 16.2 we continue to improve the C++ backend with build throughput improvements and new and improved optimizations. These build on top of our MSVC backend improvements in Visual Studio 2019 version 16.0 which we previously announced. We will be following up on many of the improvements here with their own blog posts.

Build Throughput Improvements

  • Linker improvements speeding up iteration build times with debug info by 3x (or more) on large projects. (Numbers shown are for the Unreal Engine shipping configuration)

Graph showing 3.5x speedup over 15.9 on /debug:full and 1.6x speedup on /debug:fast

  • Link times also improved under /INCREMENTAL by 2x.

New and Improved Optimizations

Inliner Improvements
  • Small functions will be inlined more if it has a branch in it and is called from a branch in a loop.
Improved Code Generation and Optimization of Intrinsics
  • Removed the overhead of some common mathematical functions (std::isnan , std::ldiv , std::lldiv) by replacing the function calls with inline assembly instructions.
  • For x86/x64 targets the optimizer will recognize some vector intrinsics working only on the lowest element and do optimizations on them including building FMA (fused multiply-add) and doing constant folding.
Vectorizer Improvements
  • Tiny reduction loops (smaller than 12 iterations) will be vectorized for /arch:AVX  and up if the elements perfectly fit the vector size.
  • Improved the code sequence generated for loops with a pointer induction variable when the auto vectorization attempt on these loops fails.
New Analysis Passes
  • Improved analysis of control flow to remove more complicated instances of branches that are provably true/false.
  • Added a new flow-sensitive restrict pointer analysis. A restrict pointer will be handled differently in regions where it can escape, i.e. be accessed outside of the current scope, than regions where it is safe to use as “restrict” pointer.
General Optimizer Improvements
  • Enable copy elision in functions where multiple objects are returned by value.
  • Improved optimization of pointer subtractions when using LTCG compilation. A pointer subtraction includes a division, which can now be optimized away in certain cases.
  • Improved optimizations to generate and simplify FMA instructions for x86/x64 platforms. This includes enabling FMA for global variables with vector type.
  • Improved code generation for C++20’s spaceship operator, which is available under /std:c++latest : better constant propagation of known values used in comparisons (e.g. std::strong_ordering::less ), and compile-time computation of constant assembly instruction results.
  • Improved memset code generation by calling the faster CRT version where appropriate instead of expanding its definition inline. Loops that store a constant value that is formed of the same byte (e.g. 0xABABABAB) now also use the CRT version of memset.
  • Improved optimization to merge identical exception handling states, saving size for C++ programs. Note: This only works under FrameHandler4, which will become the default in Visual Studio 2019 version 16.3.

We’d love for you to download Visual Studio 2019 and give it a try. As always, we welcome your feedback. We can be reached via the comments below or via email (visualcpp@microsoft.com). If you encounter problems with Visual Studio or MSVC, or have a suggestion for us, please let us know through Help > Send Feedback > Report A Problem / Provide a Suggestion in the product, or via Developer Community. You can also find us on Twitter (@VisualC) and Facebook (msftvisualcpp).

 

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Máté Ferenc Nagy-Egri 0

    Always love to hear my daily driver becoming faster. Good job, will give it a spin with my apps.

  • Koby Kahane 0

    Is there a way to disable the new memset code generation? It causes a regression in code that doesn’t link with the CRT, making it fail to link when it previously worked fine since the intrinsic version of memset was always available, even if no import library providing a memset was used.

  • Dmitri Bellic 0

    Guys, I believe you did something wrong with loop/std::map optimization…After upgrading to 16.2, my compiled program now gives some strange results. It happens only when compiled in Release mode (i.e. with optimizations enabled).

Feedback usabilla icon