@@ -5,6 +5,7 @@ use smallvec::SmallVec;
55use super :: TerminatorKind ;
66use rustc_macros:: HashStable ;
77use std:: slice;
8+ use thin_vec:: { thin_vec, ThinVec } ;
89
910use super :: * ;
1011
@@ -16,13 +17,36 @@ impl SwitchTargets {
1617 pub fn new ( targets : impl Iterator < Item = ( u128 , BasicBlock ) > , otherwise : BasicBlock ) -> Self {
1718 let ( values, mut targets) : ( SmallVec < _ > , SmallVec < _ > ) = targets. unzip ( ) ;
1819 targets. push ( otherwise) ;
19- Self { values, targets }
20+ Self { values, targets, cold_targets : ThinVec :: new ( ) }
2021 }
2122
2223 /// Builds a switch targets definition that jumps to `then` if the tested value equals `value`,
2324 /// and to `else_` if not.
2425 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+ }
2650 }
2751
2852 /// Inverse of `SwitchTargets::static_if`.
@@ -36,6 +60,14 @@ impl SwitchTargets {
3660 }
3761 }
3862
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+
3971 /// Returns the fallback target that is jumped to when none of the values match the operand.
4072 pub fn otherwise ( & self ) -> BasicBlock {
4173 * self . targets . last ( ) . unwrap ( )
@@ -352,6 +384,22 @@ impl<'tcx> TerminatorKind<'tcx> {
352384 TerminatorKind :: SwitchInt { discr : cond, targets : SwitchTargets :: static_if ( 0 , f, t) }
353385 }
354386
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+
355403 pub fn successors ( & self ) -> Successors < ' _ > {
356404 use self :: TerminatorKind :: * ;
357405 match * self {
0 commit comments