@@ -20,17 +20,29 @@ impl Timespec {
20
20
21
21
fn sub_timespec ( & self , other : & Timespec ) -> Result < Duration , Duration > {
22
22
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 )
28
38
} 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 ,
31
41
self . t . tv_nsec as u32 + ( NSEC_PER_SEC as u32 ) - other. t . tv_nsec as u32 ,
32
42
)
33
- } )
43
+ } ;
44
+
45
+ Ok ( Duration :: new ( secs, nsec) )
34
46
} else {
35
47
match other. sub_timespec ( self ) {
36
48
Ok ( d) => Err ( d) ,
0 commit comments