@@ -13,12 +13,15 @@ use std::collections::BTreeMap;
13
13
use std:: fmt;
14
14
use std:: ops:: Not ;
15
15
16
- use rustc_data_structures:: fx:: FxHashSet ;
16
+ use rustc_data_structures:: fx:: { FxHashSet , FxHasher } ;
17
17
18
18
use cranelift_codegen:: cursor:: { Cursor , FuncCursor } ;
19
19
use cranelift_codegen:: ir:: { InstructionData , Opcode , ValueDef } ;
20
20
use cranelift_codegen:: ir:: immediates:: Offset32 ;
21
21
22
+ use hashbrown:: HashSet ;
23
+ use std:: hash:: BuildHasherDefault ;
24
+
22
25
use crate :: prelude:: * ;
23
26
24
27
/// Workaround for `StackSlot` not implementing `Ord`.
@@ -45,9 +48,9 @@ impl Ord for OrdStackSlot {
45
48
46
49
#[ derive( Debug , Default ) ]
47
50
struct StackSlotUsage {
48
- stack_addr : FxHashSet < Inst > ,
49
- stack_load : FxHashSet < Inst > ,
50
- stack_store : FxHashSet < Inst > ,
51
+ stack_addr : HashSet < Inst , BuildHasherDefault < FxHasher > > ,
52
+ stack_load : HashSet < Inst , BuildHasherDefault < FxHasher > > ,
53
+ stack_store : HashSet < Inst , BuildHasherDefault < FxHasher > > ,
51
54
}
52
55
53
56
impl StackSlotUsage {
@@ -79,16 +82,14 @@ impl StackSlotUsage {
79
82
} ) . collect :: < Vec < Inst > > ( )
80
83
}
81
84
82
- fn remove_unused_stack_addr ( & mut self , func : & mut Function , inst : Inst ) {
85
+ fn remove_unused_stack_addr ( func : & mut Function , inst : Inst ) {
83
86
func. dfg . detach_results ( inst) ;
84
87
func. dfg . replace ( inst) . nop ( ) ;
85
- self . stack_addr . remove ( & inst) ;
86
88
}
87
89
88
- fn remove_unused_load ( & mut self , func : & mut Function , load : Inst ) {
90
+ fn remove_unused_load ( func : & mut Function , load : Inst ) {
89
91
func. dfg . detach_results ( load) ;
90
92
func. dfg . replace ( load) . nop ( ) ;
91
- self . stack_load . remove ( & load) ;
92
93
}
93
94
94
95
fn remove_dead_store ( & mut self , func : & mut Function , store : Inst ) {
@@ -314,19 +315,21 @@ fn remove_unused_stack_addr_and_stack_load(opt_ctx: &mut OptimizeContext<'_>) {
314
315
}
315
316
316
317
// Replace all unused stack_addr and stack_load instructions with nop.
317
- for stack_slot_users in opt_ctx. stack_slot_usage_map . values_mut ( ) {
318
- // FIXME remove clone
319
- for & inst in stack_slot_users. stack_addr . clone ( ) . iter ( ) {
320
- if stack_addr_load_insts_users. get ( & inst) . map ( |users| users. is_empty ( ) ) . unwrap_or ( true ) {
321
- stack_slot_users. remove_unused_stack_addr ( & mut opt_ctx. ctx . func , inst) ;
322
- }
323
- }
318
+ let mut func = & mut opt_ctx. ctx . func ;
324
319
325
- for & inst in stack_slot_users. stack_load . clone ( ) . iter ( ) {
326
- if stack_addr_load_insts_users. get ( & inst) . map ( |users| users. is_empty ( ) ) . unwrap_or ( true ) {
327
- stack_slot_users. remove_unused_load ( & mut opt_ctx. ctx . func , inst) ;
328
- }
329
- }
320
+ // drain_filter() on hashbrown::HashSet drains the items that do *not* match the
321
+ // predicate. Once hashbrown gets updated to match the behaviour of std::drain_filter
322
+ // (0.8.2), the predicate will have to be reversed
323
+ for stack_slot_users in opt_ctx. stack_slot_usage_map . values_mut ( ) {
324
+ stack_slot_users
325
+ . stack_addr
326
+ . drain_filter ( |inst| !( stack_addr_load_insts_users. get ( inst) . map ( |users| users. is_empty ( ) ) . unwrap_or ( true ) ) )
327
+ . for_each ( |inst| StackSlotUsage :: remove_unused_stack_addr ( & mut func, inst) ) ;
328
+
329
+ stack_slot_users
330
+ . stack_load
331
+ . drain_filter ( |inst| !( stack_addr_load_insts_users. get ( inst) . map ( |users| users. is_empty ( ) ) . unwrap_or ( true ) ) )
332
+ . for_each ( |inst| StackSlotUsage :: remove_unused_load ( & mut func, inst) ) ;
330
333
}
331
334
}
332
335
0 commit comments