@@ -16,6 +16,7 @@ use std::{
1616 slice:: Iter
1717} ;
1818use crate :: hir_type:: { Type , types} ;
19+ use crate :: bitset:: BitSet ;
1920
2021/// An index of an [`Insn`] in a [`Function`]. This is a popular
2122/// type since this effectively acts as a pointer to an [`Insn`].
@@ -39,12 +40,21 @@ impl std::fmt::Display for InsnId {
3940#[ derive( Copy , Clone , Eq , PartialEq , Hash , Debug ) ]
4041pub struct BlockId ( pub usize ) ;
4142
43+ impl Into < usize > for BlockId {
44+ fn into ( self ) -> usize {
45+ self . 0
46+ }
47+ }
48+
4249impl std:: fmt:: Display for BlockId {
4350 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
4451 write ! ( f, "bb{}" , self . 0 )
4552 }
4653}
4754
55+ type InsnSet = BitSet < InsnId > ;
56+ type BlockSet = BitSet < BlockId > ;
57+
4858fn write_vec < T : std:: fmt:: Display > ( f : & mut std:: fmt:: Formatter , objs : & Vec < T > ) -> std:: fmt:: Result {
4959 write ! ( f, "[" ) ?;
5060 let mut prefix = "" ;
@@ -1252,19 +1262,18 @@ impl Function {
12521262 }
12531263 let rpo = self . rpo ( ) ;
12541264 // Walk the graph, computing types until fixpoint
1255- let mut reachable = vec ! [ false ; self . blocks. len( ) ] ;
1256- reachable[ self . entry_block . 0 ] = true ;
1265+ let mut reachable = BlockSet :: with_capacity ( self . blocks . len ( ) ) ;
1266+ reachable. insert ( self . entry_block ) ;
12571267 loop {
12581268 let mut changed = false ;
1259- for block in & rpo {
1260- if !reachable[ block . 0 ] { continue ; }
1269+ for & block in & rpo {
1270+ if !reachable. get ( block ) { continue ; }
12611271 for insn_id in & self . blocks [ block. 0 ] . insns {
1262- let insn = self . find ( * insn_id) ;
1263- let insn_type = match insn {
1272+ let insn_type = match self . find ( * insn_id) {
12641273 Insn :: IfTrue { val, target : BranchEdge { target, args } } => {
12651274 assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
12661275 if self . type_of ( val) . could_be ( Type :: from_cbool ( true ) ) {
1267- reachable[ target . 0 ] = true ;
1276+ reachable. insert ( target ) ;
12681277 for ( idx, arg) in args. iter ( ) . enumerate ( ) {
12691278 let param = self . blocks [ target. 0 ] . params [ idx] ;
12701279 self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
@@ -1275,7 +1284,7 @@ impl Function {
12751284 Insn :: IfFalse { val, target : BranchEdge { target, args } } => {
12761285 assert ! ( !self . type_of( val) . bit_equal( types:: Empty ) ) ;
12771286 if self . type_of ( val) . could_be ( Type :: from_cbool ( false ) ) {
1278- reachable[ target . 0 ] = true ;
1287+ reachable. insert ( target ) ;
12791288 for ( idx, arg) in args. iter ( ) . enumerate ( ) {
12801289 let param = self . blocks [ target. 0 ] . params [ idx] ;
12811290 self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
@@ -1284,14 +1293,14 @@ impl Function {
12841293 continue ;
12851294 }
12861295 Insn :: Jump ( BranchEdge { target, args } ) => {
1287- reachable[ target . 0 ] = true ;
1296+ reachable. insert ( target ) ;
12881297 for ( idx, arg) in args. iter ( ) . enumerate ( ) {
12891298 let param = self . blocks [ target. 0 ] . params [ idx] ;
12901299 self . insn_types [ param. 0 ] = self . type_of ( param) . union ( self . type_of ( * arg) ) ;
12911300 }
12921301 continue ;
12931302 }
1294- _ if insn. has_output ( ) => self . infer_type ( * insn_id) ,
1303+ insn if insn. has_output ( ) => self . infer_type ( * insn_id) ,
12951304 _ => continue ,
12961305 } ;
12971306 if !self . type_of ( * insn_id) . bit_equal ( insn_type) {
@@ -1773,11 +1782,11 @@ impl Function {
17731782 }
17741783 }
17751784 }
1776- let mut necessary = vec ! [ false ; self . insns. len( ) ] ;
1785+ let mut necessary = InsnSet :: with_capacity ( self . insns . len ( ) ) ;
17771786 // Now recursively traverse their data dependencies and mark those as necessary
17781787 while let Some ( insn_id) = worklist. pop_front ( ) {
1779- if necessary[ insn_id . 0 ] { continue ; }
1780- necessary[ insn_id . 0 ] = true ;
1788+ if necessary. get ( insn_id ) { continue ; }
1789+ necessary. insert ( insn_id ) ;
17811790 match self . find ( insn_id) {
17821791 Insn :: Const { .. }
17831792 | Insn :: Param { .. }
@@ -1901,7 +1910,7 @@ impl Function {
19011910 }
19021911 // Now remove all unnecessary instructions
19031912 for block_id in & rpo {
1904- self . blocks [ block_id. 0 ] . insns . retain ( |insn_id| necessary[ insn_id . 0 ] ) ;
1913+ self . blocks [ block_id. 0 ] . insns . retain ( |& insn_id| necessary. get ( insn_id ) ) ;
19051914 }
19061915 }
19071916
@@ -1980,7 +1989,7 @@ impl Function {
19801989 VisitSelf ,
19811990 }
19821991 let mut result = vec ! [ ] ;
1983- let mut seen = HashSet :: new ( ) ;
1992+ let mut seen = BlockSet :: with_capacity ( self . blocks . len ( ) ) ;
19841993 let mut stack = vec ! [ ( start, Action :: VisitEdges ) ] ;
19851994 while let Some ( ( block, action) ) = stack. pop ( ) {
19861995 if action == Action :: VisitSelf {
0 commit comments