When _Duration uses integer seconds precision (period::den == 1,
not floating-point), time_point formatting has no sub-second
digits and therefore no locale-dependent components.  Add
__detail::__chrono_write_time that conditionally skips the locale
argument for integer-second time_points, eliminating the
format_to_n locale overload and the basic_format_context
locale member initialization.

Also add [[__gnu__::__always_inline__]] to
__formatter_chrono::_M_subsecs to mitigate a small mixed-TU
inlining regression.

libstdc++-v3/ChangeLog:

        * include/bits/chrono_io.h
        (__detail::__chrono_write_time): New function that conditionally
        skips locale for integer-second time_points.
        (__formatter_chrono::_M_subsecs): Add __always_inline__.
        (operator<< for hh_mm_ss): Use if constexpr to skip locale
        for integer-second durations.
        (operator<< for sys_time, utc_time, tai_time, gps_time,
        file_time, local_time, zoned_time): Use __chrono_write_time.

Suggested-by: Tomasz KamiƄski <[email protected]>
Signed-off-by: Anlai Lu <[email protected]>
---
Performance data (Xeon, -O2, core pinned, turbo off):

  den==1 types     instructions   branches
  ---------------  ------------   --------
  sys_time_s         -5.0%        -11.3%
  utc_time_s         -5.0%        -11.3%
  tai_time_s         -5.0%        -11.3%
  gps_time_s         -5.0%        -11.3%
  file_time_s        -5.0%        -11.3%
  local_time_s       -5.1%        -11.3%
  zoned_time_s       -2.8%         -5.3%
  hh_mm_ss_s         -7.1%        -15.7%

  den!=1:
  sys_time_ms        +0.3%         +0.6%
  utc_time_ms        +0.3%         +0.6%
  local_time_ms      +0.3%         +0.6%
  hh_mm_ss_ms        +0.4%         +0.7%

---
 libstdc++-v3/include/bits/chrono_io.h | 44 +++++++++++++++++++++------
 1 file changed, 34 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono_io.h 
b/libstdc++-v3/include/bits/chrono_io.h
index c5170368f..2cbd61ccd 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -1656,6 +1656,7 @@ namespace __format
        }
 
       template<typename _OutIter, typename _FormatContext>
+       [[__gnu__::__always_inline__]]
        _OutIter
        _M_subsecs(const _ChronoData<_CharT>& __t, _OutIter __out,
                   _FormatContext& __ctx) const
@@ -3635,6 +3636,23 @@ namespace __detail
       return std::__ostream_insert(__os, __s.data(), __s.size());
     }
 
+  // Wrapper around __chrono_write that skips locale for
+  // integer-second time_points.
+  template<size_t _BufSize, typename _TimePoint, typename _CharT,
+          typename _Traits>
+    [[__gnu__::__always_inline__]]
+    inline basic_ostream<_CharT, _Traits>&
+    __chrono_write_time(basic_ostream<_CharT, _Traits>& __os,
+                       const _TimePoint& __tp)
+    {
+      using _Duration = typename _TimePoint::duration;
+      if constexpr (!treat_as_floating_point_v<typename _Duration::rep>
+                   && _Duration::period::den == 1)
+       return __chrono_write<_BufSize>(__os, __tp);
+      else
+       return __chrono_write<_BufSize>(__os, __tp, __os.getloc());
+    }
+
 } // namespace __detail
 /// @endcond
 
@@ -3740,7 +3758,7 @@ namespace __detail
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const weekday_last& __wdl)
     { return __detail::__chrono_write<128>(__os, __wdl, __os.getloc()); }
-    
+
   template<typename _CharT, typename _Traits>
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md)
@@ -3846,7 +3864,13 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const hh_mm_ss<_Duration>& __hms)
-    { return __detail::__chrono_write<64>(__os, __hms, __os.getloc()); }
+    {
+      if constexpr (!treat_as_floating_point_v<typename _Duration::rep>
+                   && _Duration::period::den == 1)
+       return __detail::__chrono_write<64>(__os, __hms);
+      else
+       return __detail::__chrono_write<64>(__os, __hms, __os.getloc());
+    }
 
 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   /// Writes a sys_info object to an ostream in an unspecified format.
@@ -3866,7 +3890,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const zoned_time<_Duration, _TimeZonePtr>& __t)
-    { return __detail::__chrono_write<128>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<128>(__os, __t); }
 #endif
 
   template<typename _CharT, typename _Traits, typename _Duration>
@@ -3875,12 +3899,12 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const sys_time<_Duration>& __tp)
-    { return __detail::__chrono_write<64>(__os, __tp, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __tp); }
 
   template<typename _CharT, typename _Traits>
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp)
-    { return __detail::__chrono_write<32>(__os, __dp); };
+    { return __detail::__chrono_write<32>(__os, __dp); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
@@ -3914,7 +3938,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const utc_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
@@ -3946,7 +3970,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const tai_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
@@ -3982,7 +4006,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const gps_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
@@ -4017,7 +4041,7 @@ namespace __detail
     inline basic_ostream<_CharT, _Traits>&
     operator<<(basic_ostream<_CharT, _Traits>& __os,
               const file_time<_Duration>& __t)
-    { return __detail::__chrono_write<64>(__os, __t, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __t); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
@@ -4040,7 +4064,7 @@ namespace __detail
     // _GLIBCXX_RESOLVE_LIB_DEFECTS
     // 4257. Stream insertion for chrono::local_time should be constrained
     requires requires(const sys_time<_Duration>& __st) { __os << __st; }
-    { return __detail::__chrono_write<64>(__os, __lt, __os.getloc()); }
+    { return __detail::__chrono_write_time<64>(__os, __lt); }
 
   template<typename _CharT, typename _Traits, typename _Duration,
           typename _Alloc = allocator<_CharT>>
-- 
2.34.1

Reply via email to