@@ -5,6 +5,7 @@ use smallvec::SmallVec;
5
5
use super :: TerminatorKind ;
6
6
use rustc_macros:: HashStable ;
7
7
use std:: slice;
8
+ use thin_vec:: { thin_vec, ThinVec } ;
8
9
9
10
use super :: * ;
10
11
@@ -16,13 +17,36 @@ impl SwitchTargets {
16
17
pub fn new ( targets : impl Iterator < Item = ( u128 , BasicBlock ) > , otherwise : BasicBlock ) -> Self {
17
18
let ( values, mut targets) : ( SmallVec < _ > , SmallVec < _ > ) = targets. unzip ( ) ;
18
19
targets. push ( otherwise) ;
19
- Self { values, targets }
20
+ Self { values, targets, cold_targets : ThinVec :: new ( ) }
20
21
}
21
22
22
23
/// Builds a switch targets definition that jumps to `then` if the tested value equals `value`,
23
24
/// and to `else_` if not.
24
25
pub fn static_if ( value : u128 , then : BasicBlock , else_ : BasicBlock ) -> Self {
25
- Self { values : smallvec ! [ value] , targets : smallvec ! [ then, else_] }
26
+ Self {
27
+ values : smallvec ! [ value] ,
28
+ targets : smallvec ! [ then, else_] ,
29
+ cold_targets : ThinVec :: new ( ) ,
30
+ }
31
+ }
32
+
33
+ /// Builds a switch targets definition that jumps to `then` if the tested value equals `value`,
34
+ /// and to `else_` if not.
35
+ /// If cold_br is some bool value, the given outcome is considered cold (i.e., unlikely).
36
+ pub fn static_if_with_cold_br (
37
+ value : u128 ,
38
+ then : BasicBlock ,
39
+ else_ : BasicBlock ,
40
+ cold_br : Option < bool > ,
41
+ ) -> Self {
42
+ Self {
43
+ values : smallvec ! [ value] ,
44
+ targets : smallvec ! [ then, else_] ,
45
+ cold_targets : match cold_br {
46
+ Some ( br) => thin_vec ! [ if br { 0 } else { 1 } ] ,
47
+ None => ThinVec :: new ( ) ,
48
+ } ,
49
+ }
26
50
}
27
51
28
52
/// Inverse of `SwitchTargets::static_if`.
@@ -36,6 +60,14 @@ impl SwitchTargets {
36
60
}
37
61
}
38
62
63
+ pub fn cold_target ( & self ) -> Option < usize > {
64
+ if self . cold_targets . len ( ) == 1 {
65
+ Some ( self . cold_targets [ 0 ] )
66
+ } else {
67
+ None
68
+ }
69
+ }
70
+
39
71
/// Returns the fallback target that is jumped to when none of the values match the operand.
40
72
pub fn otherwise ( & self ) -> BasicBlock {
41
73
* self . targets . last ( ) . unwrap ( )
@@ -352,6 +384,22 @@ impl<'tcx> TerminatorKind<'tcx> {
352
384
TerminatorKind :: SwitchInt { discr : cond, targets : SwitchTargets :: static_if ( 0 , f, t) }
353
385
}
354
386
387
+ pub fn if_with_cold_br (
388
+ cond : Operand < ' tcx > ,
389
+ t : BasicBlock ,
390
+ f : BasicBlock ,
391
+ cold_branch : Option < bool > ,
392
+ ) -> TerminatorKind < ' tcx > {
393
+ TerminatorKind :: SwitchInt {
394
+ discr : cond,
395
+ targets : SwitchTargets :: static_if_with_cold_br (
396
+ 0 , f, t,
397
+ // we compare to zero, so have to invert the branch
398
+ cold_branch. and_then ( |b| Some ( !b) )
399
+ ) ,
400
+ }
401
+ }
402
+
355
403
pub fn successors ( & self ) -> Successors < ' _ > {
356
404
use self :: TerminatorKind :: * ;
357
405
match * self {
0 commit comments