@@ -56,6 +56,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
56
56
57
57
match expr. kind {
58
58
ExprKind :: LogicalOp { op : LogicalOp :: And , lhs, rhs } => {
59
+ // cold_branch == true is equivalent to unlikely(lhs && rhs)
60
+ // cold_branch == false is equivalent to likely(lhs && rhs)
61
+ // We propagate the expectation to the lhs and rhs operands as follows:
62
+ // likely(lhs && rhs) => likely(lhs) && likely(rhs)
63
+ // unlikely(lhs && rhs) => lhs && unlikely(rhs)
64
+ // Note that the `unlikely` propagation may be incorrect. With the information
65
+ // available, we can't tell which of the operands in unlikely.
66
+
59
67
let lhs_then_block = unpack ! ( this. then_else_break(
60
68
block,
61
69
lhs,
@@ -64,8 +72,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
64
72
variable_source_info,
65
73
declare_bindings,
66
74
match cold_branch {
67
- Some ( false ) => Some ( false ) ,
68
- _ => None ,
75
+ Some ( false ) => Some ( false ) , // propagate likely
76
+ _ => None , // but not unlikely
69
77
} ,
70
78
) ) ;
71
79
@@ -76,12 +84,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
76
84
break_scope,
77
85
variable_source_info,
78
86
declare_bindings,
79
- cold_branch,
87
+ cold_branch, // propagate both likely and unlikely
80
88
) ) ;
81
89
82
90
rhs_then_block. unit ( )
83
91
}
84
92
ExprKind :: LogicalOp { op : LogicalOp :: Or , lhs, rhs } => {
93
+ // cold_branch == true is equivalent to unlikely(lhs || rhs)
94
+ // cold_branch == false is equivalent to likely(lhs || rhs)
95
+ // We propagate the expectation to the lhs and rhs operands as follows:
96
+ // likely(lhs || rhs) => lhs || likely(rhs)
97
+ // unlikely(lhs || rhs) => unlikely(lhs) && unlikely(rhs)
98
+ // Note that the `likely` propagation may be incorrect. With the information
99
+ // available, we can't tell which of the operands in likely.
100
+
85
101
let local_scope = this. local_scope ( ) ;
86
102
let ( lhs_success_block, failure_block) =
87
103
this. in_if_then_scope ( local_scope, expr_span, |this| {
@@ -93,8 +109,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
93
109
variable_source_info,
94
110
true ,
95
111
match cold_branch {
96
- Some ( true ) => Some ( true ) ,
97
- _ => None ,
112
+ Some ( true ) => Some ( true ) , // propagate unlikely
113
+ _ => None , // but not likely
98
114
} ,
99
115
)
100
116
} ) ;
@@ -105,7 +121,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
105
121
break_scope,
106
122
variable_source_info,
107
123
true ,
108
- cold_branch,
124
+ cold_branch, // propagate both likely and unlikely
109
125
) ) ;
110
126
this. cfg . goto ( lhs_success_block, variable_source_info, rhs_success_block) ;
111
127
rhs_success_block. unit ( )
@@ -126,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
126
142
local_scope,
127
143
variable_source_info,
128
144
true ,
129
- cold_branch. and_then ( |b| Some ( !b) ) ,
145
+ cold_branch. and_then ( |b| Some ( !b) ) , // propagate the opposite of likely/unlikely
130
146
)
131
147
} ) ;
132
148
this. break_for_else ( success_block, break_scope, variable_source_info) ;
0 commit comments