Skip to content
Snippets Groups Projects
  • Jonathan Wakely's avatar
    2c492f99
    libstdc++: Micro-optimization for std::optional [PR112480] · 2c492f99
    Jonathan Wakely authored
    This small change removes a branch when clearing a std::optional<T> for
    types with no-op destructors. For types where the destructor can be
    optimized away (e.g. because it's trivial, or empty and can be inlined)
    the _M_destroy() function does nothing but set _M_engaged to false.
    Setting _M_engaged=false unconditionally is cheaper than only doing it
    when initially true, because it allows the compiler to remove a branch.
    
    The compiler thinks it would be incorrect to unconditionally introduce a
    store there, because it could conflict with reads in other threads, so
    it won't do that optimization itself. We know it's safe to do because
    we're in a non-const member function, so the standard forbids any
    potentially concurrent calls to other member functions of the same
    object. Making the store unconditional can't create a data race that
    isn't already present in the program.
    
    libstdc++-v3/ChangeLog:
    
    	PR libstdc++/112480
    	* include/std/optional (_Optional_payload_base::_M_reset): Set
    	_M_engaged to false unconditionally.
    2c492f99
    History
    libstdc++: Micro-optimization for std::optional [PR112480]
    Jonathan Wakely authored
    This small change removes a branch when clearing a std::optional<T> for
    types with no-op destructors. For types where the destructor can be
    optimized away (e.g. because it's trivial, or empty and can be inlined)
    the _M_destroy() function does nothing but set _M_engaged to false.
    Setting _M_engaged=false unconditionally is cheaper than only doing it
    when initially true, because it allows the compiler to remove a branch.
    
    The compiler thinks it would be incorrect to unconditionally introduce a
    store there, because it could conflict with reads in other threads, so
    it won't do that optimization itself. We know it's safe to do because
    we're in a non-const member function, so the standard forbids any
    potentially concurrent calls to other member functions of the same
    object. Making the store unconditional can't create a data race that
    isn't already present in the program.
    
    libstdc++-v3/ChangeLog:
    
    	PR libstdc++/112480
    	* include/std/optional (_Optional_payload_base::_M_reset): Set
    	_M_engaged to false unconditionally.