about summary refs log tree commit diff
path: root/library/std/src/sys/unix
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-15 03:08:03 +0000
committerbors <bors@rust-lang.org>2020-08-15 03:08:03 +0000
commit45060c2a66dfd667f88bd8b94261b28a58d85bd5 (patch)
treeaa173050fa295a736d6ab1e5a1a23529262e1b9b /library/std/src/sys/unix
parent668a34e0f438d4a950b9440239656d6755ad963c (diff)
parent29a946203aeebdd0d8466968705694fea9ca866f (diff)
downloadrust-45060c2a66dfd667f88bd8b94261b28a58d85bd5.tar.gz
rust-45060c2a66dfd667f88bd8b94261b28a58d85bd5.zip
Auto merge of #75549 - tmandry:rollup-sxjwa0w, r=tmandry
Rollup of 4 pull requests

Successful merges:

 - #75376 (Set CMAKE_SYSTEM_NAME when cross-compiling)
 - #75448 (merge `as_local_hir_id` with `local_def_id_to_hir_id`)
 - #75513 (Recover gracefully from `struct` parse errors)
 - #75545 (std/sys/unix/time: make it easier for LLVM to optimize `Instant` subtraction.)

Failed merges:

 - #75514 (Replaced `log` with `tracing`)

r? @ghost
Diffstat (limited to 'library/std/src/sys/unix')
-rw-r--r--library/std/src/sys/unix/time.rs28
1 files changed, 20 insertions, 8 deletions
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 6707f790cab..f2a9cb5a0e8 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -20,17 +20,29 @@ impl Timespec {
 
     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
         if self >= other {
-            Ok(if self.t.tv_nsec >= other.t.tv_nsec {
-                Duration::new(
-                    (self.t.tv_sec - other.t.tv_sec) as u64,
-                    (self.t.tv_nsec - other.t.tv_nsec) as u32,
-                )
+            // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
+            // to optimize it into a branchless form (see also #75545):
+            //
+            // 1. `self.t.tv_sec - other.t.tv_sec` shows up as a common expression
+            //    in both branches, i.e. the `else` must have its `- 1`
+            //    subtraction after the common one, not interleaved with it
+            //    (it used to be `self.t.tv_sec - 1 - other.t.tv_sec`)
+            //
+            // 2. the `Duration::new` call (or any other additional complexity)
+            //    is outside of the `if`-`else`, not duplicated in both branches
+            //
+            // Ideally this code could be rearranged such that it more
+            // directly expresses the lower-cost behavior we want from it.
+            let (secs, nsec) = if self.t.tv_nsec >= other.t.tv_nsec {
+                ((self.t.tv_sec - other.t.tv_sec) as u64, (self.t.tv_nsec - other.t.tv_nsec) as u32)
             } else {
-                Duration::new(
-                    (self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+                (
+                    (self.t.tv_sec - other.t.tv_sec - 1) as u64,
                     self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.t.tv_nsec as u32,
                 )
-            })
+            };
+
+            Ok(Duration::new(secs, nsec))
         } else {
             match other.sub_timespec(self) {
                 Ok(d) => Err(d),