Consider use of __builtin_launder

Issue #481 resolved
Dan Bonachea created an issue

The UPC++ runtime sometimes needs to "launder" pointers, creating a valid T* using bits that didn't previously meet the C++ definition of a valid T*. This notably arises in detail::raw_storage which is used to create storage for objects while maintaining "manual" control over their construction and destruction.

We do our laundry using detail::launder() which uses std::launder when available. Unfortunately the latter is a C++17 feature, which means it's only available in some of the newest compiler versions, and even then only when the header (read: the application code) is built using -std=c++17 or greater. Here's the current overview of where std::launder available:

  • g++ 6.4.0, clang++ 4.0.0, intel 17.2 (our floors) DON’T support std::launder at all
  • GNU g++ 7.1.0…10.3.0 DO support, but only for language levels >= 17
  • same with GNU g++ 11.1.0+, although this compiler defaults to c++17
  • LLVM clang 8.0.0+ DO support, but only for language levels >= 17
  • Intel 18.0+ DO support, but only for language levels >= 17
  • PGI does not support std::launder at all

In the absence of std::launder, we use an inline volatile asm with GNU-style dependency annotations that tell the compiler we "killed" the memory in question, so the analysis has to conservatively assume we may have constructed an object in that memory. This mostly works, but is overkill and probably hurts the analysis more than necessary (especially for "less robust" compilers whose analysis doesn't fully understand the GNU asm annotations and might just conservatively treat every asm as potentially killing all of memory).

@Colin MacLean has suggested (and I agree) that we could instead use __builtin_launder (when available) as a more surgical approach when std::launder is missing for whatever reason. It appears __builtin_launder was added in GCC 7.1.0 (2017) / clang 8.0.0 (2019) / intel 2018.1 - so pretty much the same version space, but unlike std::launder it is available in all language modes.

FWIW __has_builtin(__builtin_launder) does NOT appear to be reliably precise for detecting this feature, as (based on my testing) GCC doesn't answer "yes" for that until v10.1 -- so we should probably use a configure check for __builtin_launder instead.

Comments (2)

  1. Log in to comment