Code Generation for Xbox One Best Practices

By: Advanced Technology Group

Updated: April 28, 2017

In this topic

C++ conformance

Floating-point computations

Virtual methods

Exception handling

Intrinsics support

Calling convention

Code analysis

Security

Code porting recommendations

Optimization recommendations

Additional recommendations

Resources

Version history

C++ conformance

Visual C++ implements C++11 and C++14 language standard features, as well as some C++17 draft features. Xbox One titles can take advantage of the performance and usability of these features in both the language and the C++ Standard Library.

Table 1. Comparison of C++11/C++14 language features in Visual Studio.

C++11/C++14 language feature VS 2012 VS 2015 VS 2017
nullptr ✓ ✓ ✓
static_assert ✓ ✓ ✓
override / final* ✓ ✓ ✓
Lambda expressions ✓ ✓ ✓
Rvalue references ✓ ✓ ✓
decltype ✓ ✓ ✓
auto ✓ ✓ ✓
Strongly typed enumerations ✓ ✓ ✓
Forward declared enumerations ✓ ✓ ✓
Ranged-based for loops ✓ ✓ ✓
Variadic templates   ✓ ✓
Uniform initialization and initializer lists   ✓ ✓
Delegating constructors   ✓ ✓
Raw string literals   ✓ ✓
Explicit conversion operators   ✓ ✓
Default template arguments for function templates   ✓ ✓
Alias templates   ✓ ✓
Defaulted functions   ✓ ✓
Deleted functions   ✓ ✓
Non-static data member initializers (NSDMIs)   ✓ ✓
Attributes, constexpr, ref-qualifiers, inheriting constructors, char16_t, char32_t, Unicode string literals, user-defined literals (UDLs), extended sizeof, inline namespaces, unrestricted unions, noexcept, thread_local, magic statics, universal character names in literals   ✓ ✓
C99: func, long long   ✓ ✓
Expression SFINAE   Update 1
Update 3
✓
C++14: Sized deallocation   ✓ ✓
C++14: New rules for auto with braced-init-lists, attributes for namespaces and enumerators, typename in template template-parameters; removing trigraphs, u8 character literals   Update 2 ✓
C++14: Extended constexpr     ✓
C++14: Non-Static Data Member Initilizer (NSDMI) for aggregates     ✓

Note: For more on the VS 2017 related C++14 changes, see the Visual C++ team blog.

Table 2. Comparison of C++11/C++14 headers in Visual Studio.

C++11/C++14 header VS 2012 VS 2015 VS 2017
<array>, <memory>, <random>, <regex>, <tuple>, <type_traits>, <unordered_map>, <unordered_set> &check; &check; &check;
<stdint.h>, cstdint &check; &check; &check;
unique_ptr &check; &check; &check;
cbegin(), cend(), crbegin(), crend() &check; &check; &check;
<forward_list> &check; &check; &check;
<algorithm> and <exception> updates find_if_not, copy_if, is_sorted,etc. exception_ptr &check; &check; &check;
<allocators> &check; &check; &check;
<codecvt> &check; &check; &check;
<system_error> &check; &check; &check;
emplace(), emplace_front(), emplace_back(), etc. &check; &check; &check;
<chrono>* &check; &check; &check;
<ratio> &check; &check; &check;
<scoped_allocator> &check; &check; &check;
<atomic>, <condition_variable>, <future>, <mutex>, <thread> &check; &check; &check;
<intializer_list>   &check; &check;
C99: <stdbool.h>, <complex.h> / <ccomplex>, <fenv.h> / <cfenv>, <inttypes.h> / <cinttypes>, <ctgmath>   &check; &check;
C99: <uchar.h> / <cuchar>   &check; &check;
C99: <tgmath.h>, some printf format specifiers   &check; &check;
C++14: insert_or_assign/try_emplace for map   &check; &check;
C++14: make_unique   &check; &check;
C++14: non-member size(), empty(), data()   &check; &check;
C++14: shared_mutex. shared_mutex_timed   &check; &check;
C++14: UDLs usage in Standard C++ Library   &check; &check;
C++14: constexpr use in Standard C++ Library   Update 1 &check;

For more information, see the following resources on MSDN:

In Visual Studio 2015 Update 3 and Visual Studio 2017, the compiler now offers a new standards version switch to control access to newer C++ draft features. By default, the compiler will only support C++11/C++14 (/std:c++14). You can also access C++17 draft features (/std:c++latest). For more information, see the Visual C++ Team Blog.

Floating-point computations

The x64 native programming model exclusively uses SSE/SSE2 instructions for floating-point math computations. The compiler never generates the older x87 FPU instructions (as used for Windows x86) which are deprecated for x64 native code. This difference has a number of implications:

Floating-point control word

SSE/SSE2 makes use of a control word similar to the x87 FPU control word which is manipulated by the controlfp_s function. Here are some recommendations for using the control word:

The SSE control word is a per-thread setting, and modifying the control word is a potentially low-performance operation so such changes should be minimized. There is an SSE4.1 intrinsic (_mm_round_ps) that can perform various rounding operations explicitly without needing to modify the control word. SSE2 intrinsics (_mm_cvttsd_si32, _mm_cvttss_si32) can convert to an integer with explicit truncation without changing the control word as well.

Auto-vectorizer

The Visual C++ compiler includes an auto-vectorizer that can improve the utilization of the SIMD instruction set and registers automatically for scalar integer and floating-point code. Explicit use of SIMD intrinsics or DirectXMath (see below) can be a more efficient approach, but the auto-vectorizer can provide a speed-up for existing code or scalar algorithms that are difficult to explicitly vectorize. Auto-vectorization is enabled with /O2 or /Ox. You can disable it for specific loops using #pragma(loop(no_vector)). /Qvec-report:2 can be used to generate a report on which loops were vectorized and why other loops were not.

There is a distinct auto-parallelization feature available as well by way of the /Qpar compiler switch and #pragma(loop(hint_parallel(n))). This feature will parallelize loops using multiple threads to scale across multiple cores. You can use /Qpar-report:2 to generate a report.

For more information, see Auto-Parallelization and Auto-Vectorization and Auto-Vectorizer in Visual Studio 11 on MSDN.

Virtual methods

With the Xbox One out-of-order execution CPU and full-featured branch-predictor, the use of virtual methods is no longer a major performance challenge. It is still helpful to not over-generalize your object design (that is, using a base class, with virtual methods, which only ever has a single instantiated derived type for the life of the game), but you no longer need to go to great lengths to avoid virtual methods as was suggested for Xbox 360. This guidance also extends to the Pimpl idiom, which has less of a performance impact on Xbox One than it did on Xbox 360. It is still important to minimize or eliminate calls to essentially random branch targets, so some care when using polymorphism is justified.

Note Use of the new C++11 keywords override and final make using virtual methods in C++ less error-prone.

Visual Studio 2015 Update 2: Be sure to read up on the __declspec(empty_bases) optimization on the Visual C++ Team Blog.

Exception handling

Game developers have a long history of avoiding the use of exception handling (EH), both Structured Exception Handling and C++ Exception Handling. For the Xbox 360 console, EH was officially unsupported. For Xbox One, however, EH is an assumed aspect of the platform. The C++ Standard Library (also known as the Standard Template Library / STL) and the Windows Runtime (WinRT) APIs both rely on exception handling for their error reporting and handling.

For x64 native code, EH does not have any direct code impacts on the function epilogue or prologue. While Windows x86 used a stack-based scheme that involved additional code injected into the modules, x64 native code generation uses a table-based scheme to ensure the stack can be properly unwound during exception processing. The table-based scheme used by x64 native also has the advantage of being more secure because it is not subject to stack buffer overrun attacks. This design has a number of implications:

Developers should not attempt to disable EH, which as noted above cannot be completely eliminated for x64 native code in any case, and should use ‘exception-safe’ coding patterns. Primarily this impacts resource allocation (memory, file handles, locks, and so forth.). The C++11 Standard Library provides a plethora of ready-made tools for ensuring code is exception-safe including std::shared_ptr, std::unique_ptr, std::lock_guard, and various C++ Standard Library containers (array, vector, and so forth). Your code should never have to explicitly call delete to properly clean up memory resources. This technique is known as Resource Acquisition Is Initialization (RAII).

For cases that are not directly supported by the C++ Standard Library, simple customizations can solve the problems just as effectively.

Table 3. Traditional C++ vs. Exception-safe C++.

Traditional C++ Exception-safe C++
MyObject *obj = new MyObject; std::unique_ptr
obj(new MyObject);

-or-

std::shared_ptr
obj( make_shared() );
BYTE* buffer = new BYTE[ 2048 ]; std::array<uin8_t, 2048> buffer;

-or-

std::unique_ptr<uint8_t[]>
buffer( new uint8_t[2048]; )
float* buffer = _aligned_malloc( 2048, 16 ); struct aligned_deleter
{
void operator()(void* p)
{ _aligned_free(p); }
};

std::unique_ptr<float, aligned_deleter>
buffer( _aligned_malloc(2048,16) ) ;
HANDLE h = CreateFile(…);
if ( h == INVALID_HANDLE)
// error
struct handle_closer
{
void operator()(HANDLE h)
{
assert(h != INVALID_HANDLE_VALUE);
if (h) CloseHandle(h);
}
};

inline HANDLE safe_handle( HANDLE h )
{
return (h==INVALID_HANDLE_VALUE) ? 0:h;
}

std::unique_ptr<void, handle_closer>
hFile( safe_handle( CreateFile2(…) ) );
if ( !hFile )
// error
CRITICAL_SECTION cs;
InitializeCriticalSection
(&cs);

EnterCriticalSection(&cs);

LeaveCriticalSection(&cs);
std::mutex m;

{
std::lock_guard lock(m);
/* lock on m held until end of scope */
}
ID3D11InputLayout*
inputLayout = NULL;

device->CreateInputLayout( …, &inputLayout );

SAFE_RELEASE(inputLayout);
#include <wrl/client.h>

Microsoft::WRL::ComPtr inputLayout;

device->CreateInputLayout(…, &inputLayout )

-or-

device->CreateInputLayout(…, inputLayout.ReleaseAndGetAddressOf() )

Note When passing these objects to other functions, you can pass raw pointers and use .get on the memory control object on each call, or pass the smart pointer object. When using smart pointer objects as parameters, pass them by constant reference, similar to other C++ Standard Library containers, in order to avoid additional temporary copies and to avoid excessive reference count increment and decrement cycles.

See Exception Handling (x64) on MSDN.

Exception handling recommendations

See Exception Handling (Debugging) on MSDN and A Pragmatic Look at Exception Specifications on GotW.ca.

Intrinsics support

The Visual C++ compiler supports a wide variety of intrinsics sets. Considering that x64 native programming does not support inline assembly, intrinsics are the primary method for utilizing specific CPU instructions in code.

Table 4. Intrinsics headers and descriptions.

Header Description
intrin.h General intrinsics, notably __cpuid and various intrinsics forms of the CRT routines.
ammintrin.h FMA4 and XOP intrinsics (formerly known as “SSE5”); BMI, LWP, and TBM intrinsics
Note that FMA4 and XOP are not supported by the Xbox One console.
xmmintrin.h SSE intrinsics and the __m128 type (single-precision float SIMD)
emmintrin.h SSE2 intrinsics and the __m128i/__m128d types (double-precision float and integer SIMD)
pmmintrin.h SSE3 intrinsics (horizontal adds and subtracts float/double operations, specific ‘dup’ operations)
tmmintrin.h SSSE3 intrinsics (more horizontal ops, integer abs, ‘byte’ shuffle to augment SSE2)
smmintrin.h SSE4.1 intrinsics (dot-product, rounding, augmented min/max support for SSE2)
nmmintrin.h SSE4.2 intrinsics
immintrin.h AVX, FMA3, F16C/CVT16, and AVX2 intrinsics
Note that FMA3 and AVX2 are not supported by the Xbox One console.
wmmintrin.h AES intrinsics

Note mmintrin.h is for Intel MMX™ intrinsics (including the __m64 type), which are not supported for x64 native applications.

mm3dnow.h is for AMD’s 3DNow!™ intrinsics which are not supported for x64 native applications. The exception to this is _m_prefetch / _m_prefetchw which is supported for x64 native code generation. These intrinsics are also defined in intrin.h.

The DirectXMath library is the best starting place for utilizing SIMD intrinsics in your title. It supports Windows running on systems based on x86, on x64, and on ARM; it also supports Windows Store apps and the Xbox One console. It is the successor to the xboxmath/XNAMath library on Xbox 360. On Xbox One, DirectXMath takes advantage of SSE, SSE2, SSE3, SSE4.1, AVX, and F16C instructions.

Note The Xbox One XDK (March 2017) and the Windows 10 Creators Update SDK include DirectXMath 3.10. It is also available on GitHub.

See the following resources:

Calling convention

Native code generation for x64 uses a simple and standard __fastcall calling convention that can pass the first four parameters in-register.

These points mean that shorter function signatures are better performing, and passing pointers (or references) to objects is faster than passing by value. The calling convention will automatically pass by reference objects larger than 8 bytes.

SIMD values are never passed in-register with the __fastcall scheme.

With the new Visual Studio compiler in the Xbox One XDK, there is an optional calling convention available known as __vectorcall for x64 native code generation.

The __vectorcall convention can also handle homogeneous vector aggregate (HVA) types, which consist of one or more of the same kind of vector or floating-point types—up to four members (struct XMMATRIX { __m128 v[4]; } is an HVA).

As a by value parameter, an HVA will be passed in register if sufficient space is available in XMM0/YMM0 – XMM5/YMM5 after allocating other parameters. As a return value, an HVA is returned via XMM0/YMM0 – XMM3/YMM3.

Note __vectorcall does not support vararg functions, __vectorcall is not supported in Managed C++ (/clr) contexts, and __vectorcall cannot be applied to WinRT APIs.

DirectXMath makes use of inlining, but the latest version (3.05 and later) is also annotated to use __vectorcall in cases where the compiler does not make use of inlining.

For code that makes use of the DirectXMath calling convention types (for example, FXMVECTOR, GXMVECTOR, and CXMMATRIX), consider adopting the new calling-convention macro and changes:

XMMATRIX MyFunction (FXMVECTOR v1, FXMVECTOR v2, FXMVECTOR v3,GXMVECTOR v4, CXMVECTOR v5, CXMVECTOR v6, CXMVECTOR v7 );
->
XMMATRIX XM_CALLCONV MyFunction (FXMVECTOR v1, FXMVECTOR v2, FXMVECTOR v3,GXMVECTOR v4, HXMVECTOR v5, HXMVECTOR v6, CXMVECTOR v7 );

XMVECTOR MyFunction2( CXMMATRIX M1, CXMMATRIX M2);
->
XMVECTOR XM_CALLCONV MyFunction2( FXMMATRIX M1, CXMMATRIX M2);

See Overview of x64 Calling Conventions on MSDN and the Visual C++ Team Blog.

Code analysis

Static code analysis (/analyze) is supported in all editions of Visual C++ (including “Express”) and is recommended for use by all developers. The Visual Studio IDE provides easy methods for running static code analysis, as well as making it easier to navigate the warnings and suppress any noise.

Visual C++ implements a new release of the Standard Annotation Language (SAL2) and this annotation is present in all the platform headers provided in the Xbox One XDK. Developers should consider making use of SAL2 annotation in their own code, particularly shared libraries used across the project and with other teams. Existing code bases that are making use of Windows-style SAL (__in) should be updated to the new SAL form. Converting VS-style SAL (_In_), introduced with Visual Studio 2008, to SAL2 is fairly straightforward. Here are some equivalents for various forms of SAL.

Table 5. Windows-style SAL vs Visual Studio-style SAL vs SAL2 (Standard Annotation Language).

Windows-style SAL Visual Studio-style SAL SAL2
_in _In In  
__in_opt In_opt In_opt
__out Out Out
__out_opt Out_opt Out_opt
__inout Inout Inout
_inout_opt Inout_opt Inout_opt
__in_ecount(count) In_count(count) In_reads(count)
__in_ecount(constexpr) In_count_c(constexpr) In_reads(constexpr)
__in_bcount(count) In_bytecount(count) In_read_bytes(count)
__in_xcount(count) In_count_x(count) In_reads(Inexpressible(count))
__in_ecount_opt(count) In_opt_count(count) In_reads_opt(count)
__out_ecount(count) Out_cap(count) Out_writes(count)
__out_ecount(constexpr) Out_cap_c(constexpr) Out_writes(constexpr)
__out_bcount(count) Out_bytecap(count) Out_writes_bytes(count)
__out_xcount(count) Out_cap_x(count) Out_writes(Inexpressible(count))
__inout_ecount(count) Inout_cap(count) Inout_updates(count)
__inout_ecount(cexpr) Inout_cap_c(cexpr) Inout_updates(cexpr)
__inout_bcount(count) Inout_bytecap(count) Inout_updates_bytes(count)
__deref_out Deref_out Outptr
__deref_opt_out Deref_opt_out Outptr_opt

SAL2 can handle more complex expressions for the count than older versions of SAL, so you can often successfully remove the _Inexpressible_ modifier. Another improvement with SAL2 is the introduction of the _Use_decl_annotations_ macro, which you can put on the body of a function to ensure it uses the same SAL2 annotation present on the declaration prototype rather than having to duplicate the annotation.

Note The annotations _Check_return_ and _Must_inspect_result_ can help mitigate some of the risks of using traditional error codes where developers forget to check important result codes.

See Understanding SAL, and What’s New in Code Analysis for Visual Studio 11 on MSDN.

Security

Code security is important for any gaming platform, and taking basic precautions can help to ensure that an Xbox One title itself won’t be subject to tampering or other exploits. Regular use of static code analysis can help prevent bugs with buffer overruns and other correctness issues. In addition, there is a new /sdl switch in the compiler that enables a number of useful features for ensuring good quality code security. Use of this switch is encouraged, which is labeled as SDL Checks in the Visual Studio property dialogs. This setting is particularly useful when compiling older codebases or third-party code. For newer code that is cleaned up well using /analyze, just enabling the warnings (ideally /Wall) and enabling standard buffer checks (/GS) is likely sufficient.

The Visual C++ compiler implements the existing stack cookie security check when using /GS, and performs a new range check in some specific cases that have shown up in security bugs. The range check is added when using a fixed known size array of element size 1 or 2, and a value of 0 is being written (typically a nul marker for an ASCII or Unicode string). The Visual C++ optimizer also has improved logic for removing unnecessary security checks to minimize potential performance impact from using /GS.

For more information, see the following MSDN blog posts:

Safer CRT

Visual C++ includes support for the Safer C Runtime, which includes more secure forms of the various standard C routines. Use of these safer versions is strongly encouraged, and is also recommended over the older <strsafe.h> header. Use of the _CRT_SECURE_NO_WARNINGS compilation defined in Xbox One projects is discouraged. Instead, you should clean up the various warnings in code to ensure the title is not using the insecure versions of C Runtime (CRT) routines.

See Security Features in the CRT on MSDN.

Code porting recommendations

Many Xbox One developers will have code bases written for Xbox 360, Windows x86, or other platforms. Developers who have already ported to the Windows x64 or other 64-bit platform will have addressed these issues including pointer truncation, legacy APIs, removal of assembly code, binary file structure mismatch, and reliance on 32-bit only libraries. Here are some recommendations for writing x64 native portable code:

struct MyObject {
	uint32_t count;
	void* ptr;
	uint32_t flags;
	void* next;
};

struct MyObject {
	void* ptr;
	void* next;
	uint32_t count;
	uint32_t flags;
};

For more information, see the following MSDN resources:

Optimization recommendations

While many source-level and algorithm-level optimization techniques remain the same for x64 native programming for Xbox One, it is important not to assume that hotspots will remain in the same place across platforms. Profiling of x64 native code is the only way to be sure that a given optimization effort is likely to be fruitful. This section provides some general guidance, but is no substitute for real-world measurements.

Note: VS 2015 Update 3 and VS 2017 include a new C++ code optimizer based on Static Single Assignment (SSA). For more information, see the Visual C++ blog.

Memory alignment

The x64 native platform will automatically handle misaligned reads similarly to x86, but there is still a performance penalty. Using natural alignment for data structures will help prevent excessive misalignment penalties.

The default memory allocation routines (new and malloc) return 16-byte aligned memory for the x64 native platform. The __declspec(align()) directive is useful for structures allocated on the stack as local variables or in the global data segment, but does not affect the alignment of such structures when allocated from the heap. The __aligned_malloc function is used to ensure any other alignment for heap allocations than the default of 16 bytes. Windows x86 heap allocation functions use 8-byte alignment, while Xbox 360 also uses 16 bytes.

Use of C++ Standard Library containers, make_shared<>, conversions to Windows Runtime types, and/or derivation from other classes can impact the final alignment of objects in memory.

While read and write alignment can both be useful for best performance, it is generally more important to write to aligned memory than it is to read from aligned memory. Therefore, if having to trade off one for the other, ensure that memory writes are aligned.

__restrict keyword

This keyword has been supported for providing a hint to the compiler about pointer aliasing since Visual Studio 2005. Similar to Xbox 360, it is important to make good use of this keyword to improve the utilization of the register file of the x64 native code-generation model.

Use /O1 /Oi for general optimization, /Ox for ‘hot’ modules

For Xbox 360, we recommended always using optimize for time due to the in-order execution of the processor. For the out-of-order execution CPU on Xbox One, fitting a code segment into the instruction cache is usually more important than the absolutely fastest version of the code, so optimize for space is preferred. Reserve the use of optimize for time only for specific modules or functions. Intrinsics generation is worth the additional code for games as it improves floating-point performance. You can also enable optimize for time on a specific function or set of functions by surrounding it with #pragma optimize( “t”, on) / #pragma optimize( “”, on ). Remember that optimize for time (/O2 or /Ox) can result in a drastic increase in program size due to aggressive loop unrolling.

Note The SIMD auto-vectorizer optimizations are only enabled for /O2 or /Ox. Profile-Guided Optimization (PGO) can make better choices about where exactly to apply optimize for time vs. optimize for space.

/fp:fast compiler switch

The /fp flag introduced with Visual Studio 2005 controls the various floating-point models used by the compiler (fast, precise, strict, except). The fast floating-point model uses a number of optimizations that are not part of the core “C” rules. The precise floating-point model disables these extra optimizations and is the default. Using /fp:fast is recommended for games.

See /fp.

/arch compiler switch

The implied default for x64 native platforms is /arch:SSE2. For the Xbox One console you should make use of /arch:AVX. The primary benefit is that this causes the compiler to generate VEX prefix versions of SSE instructions that use a non-destructive 3-op encoding instead of the standard 2-op encoding where one of the source operands is overwritten by the result. This affects both scalar floating-point for x64 native code using SSE instructions and explicit use of SSE intrinsics. This helps reduce register scheduling pressure and can eliminate some movaps instructions.

/favor compiler switch

The /favor switch controls the x64 compiler optimization choices for AMD64 versus Intel 64 processors. For Xbox One, use /favor:AMD64.

Whole program optimization

While traditional compiler optimization techniques can optimize functions and modules, Whole Program Optimization, also known as Link Time Code Generation (LTCG), performs optimizations across modules. This includes improved register allocation and scheduling with better knowledge of side effects, interprocedural const/range propagation, partial inlining, and de-virtualizing function calls on objects where possible.

See /GL, /Gw, and /LTCG on MSDN.

Profile-guided optimization

Profile-Guided Optimization (PGO) takes the LTCG process one step further where the whole program optimization is controlled by performance traces gathered in prior runs of the application. This improves the quality of the existing optimizations as well as optimizations for function layout, block layout, and code separation for improved working-set and branch prediction.

See Profile-Guided Optimizations on MSDN.

Note Large EXEs can exhaust the virtual memory available to the 32-bit x64 cross compiler toolset. You will likely have more success using the 64-bit native x64 compiler toolset. By default, the Visual Studio IDE uses the 32-bit x64 cross compiler. You can cause the IDE to utilize the 64-bit native x64 compiler by setting the environment variable PreferredToolArchitecture to x64 (was _IsNativeEnvironment to true for Visual Studio 2012) before launching the IDE.

Note You cannot use PGO and OpenMP together. If needed, isolate your OpenMP code to a static library while using PGO for the remainder of your application.

/OPT:REF,ICF linker switch

These eliminate redundant content in the various object modules when linked into the final executable. Typically, these are disabled for Debug builds, but should be present for Release builds.

Additional recommendations

/GS compiler switch

The use of the buffer check in release configurations is recommended for all code. For cases where there are specific buffers that are safe from security threats, but performance seems impacted by the check, use __declspec(safebuffers) on the function rather than globally disabling /GS. For higher-risk code, use #pragma strict_gs_check(on).

See /GS on MSDN.

/homeparams compiler switch

The use of this switch in optimized builds can greatly increase the debug-ability of release builds of your application. If used for production builds, it can simplify the process of analyzing and debugging crash dumps. This adds a small amount of overhead for storing additional parameters on the stack, but in most cases this does not have a noticeable impact on performance.

See /homeparams on MSDN.

/Zc:inline compiler switch

This applies the more strict C++11 rules for inline function declaration, which requires that the body of all inline functions be present in the same compilation unit as the declaration and their use. Using this flag can improve build times, and can reduce the size of .obj files significantly. If your inline functions fail to be C++11 conforming, you will get LNK2019 errors at link time.

/Zc:throwingNew compiler switch

The C++ Standard and the Standard C++ Library templates require that operator new will throw an exception rather than return nullptr on a failed allocation—you can use std::nothrow with new to force the return nullptr behavior. The Visual C++ compiler has long generated a check for null after each call to new, which is unnecessary in the presence of exception handling. By using this switch, the extra checks are eliminated. For more details, see the Visual C++ blog.

/volatile:iso compiler switch

The keyword volatile has a number of Microsoft-specific extended behaviors related to its behavior that are not really portable even between generations of Visual C++. You might consider turning on this switch and then ensuring that you aren’t misusing volatile in your code.

/permissive- compiler switch

Visual Studio 2017 has introduced a new standard conformance switch to replace the outdated /Za switch. This switch causes the compiler to emit errors and warnings when using Microsoft-specific extension behavior that could cause problems when porting to other compilers. For more information, see the Visual C++ blog.

/NXCOMPAT and /SAFESEH linker switches

These two switches are implicit when using x64 native targets. The no-execute (NX) protection is required for Xbox One titles.

See /NXCOMPAT and /SAFESEH on MSDN.

/DYNAMICBASE linker switch

This switch enables the use of address space layout randomization (ASLR) and is required for Xbox One titles.

See /DYNAMICBASE on MSDN.

/Debug:FASTLINK linker switch

For local builds, enabling this linker switch can greatly improve build iteration times. For more information, see the Visual C++ Team Blog.

Resources

Processor software optimization manuals

Presentations

MSDN Magazine articles

Version history

Date Updates
April 2017 Updates for Visual Studio 2017
June 2016 Updates for Visual Studio 2015 Updates 1, 2, and 3
September 2015 Updates for Visual Studio 2015; more resources
September 2013 Additional intrinsics notes; more resources
August 2013 Refreshed some links; more resources
May 2013 Updated for new Visual Studio compiler in the Xbox One XDK 2013 releases
August 2012 Updated for Visual Studio 2012 RTM
June 2012 Updated for the Visual Studio 2012 Release Candidate
April 2012 Original release using Visual Studio 11 Beta