@@ -20,17 +20,29 @@ impl Timespec {
2020
2121 fn sub_timespec ( & self , other : & Timespec ) -> Result < Duration , Duration > {
2222 if self >= other {
23- Ok ( if self . t . tv_nsec >= other. t . tv_nsec {
24- Duration :: new (
25- ( self . t . tv_sec - other. t . tv_sec ) as u64 ,
26- ( self . t . tv_nsec - other. t . tv_nsec ) as u32 ,
27- )
23+ // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
24+ // to optimize it into a branchless form (see also #75545):
25+ //
26+ // 1. `self.t.tv_sec - other.t.tv_sec` shows up as a common expression
27+ // in both branches, i.e. the `else` must have its `- 1`
28+ // subtraction after the common one, not interleaved with it
29+ // (it used to be `self.t.tv_sec - 1 - other.t.tv_sec`)
30+ //
31+ // 2. the `Duration::new` call (or any other additional complexity)
32+ // is outside of the `if`-`else`, not duplicated in both branches
33+ //
34+ // Ideally this code could be rearranged such that it more
35+ // directly expresses the lower-cost behavior we want from it.
36+ let ( secs, nsec) = if self . t . tv_nsec >= other. t . tv_nsec {
37+ ( ( self . t . tv_sec - other. t . tv_sec ) as u64 , ( self . t . tv_nsec - other. t . tv_nsec ) as u32 )
2838 } else {
29- Duration :: new (
30- ( self . t . tv_sec - 1 - other. t . tv_sec ) as u64 ,
39+ (
40+ ( self . t . tv_sec - other. t . tv_sec - 1 ) as u64 ,
3141 self . t . tv_nsec as u32 + ( NSEC_PER_SEC as u32 ) - other. t . tv_nsec as u32 ,
3242 )
33- } )
43+ } ;
44+
45+ Ok ( Duration :: new ( secs, nsec) )
3446 } else {
3547 match other. sub_timespec ( self ) {
3648 Ok ( d) => Err ( d) ,
0 commit comments