@@ -23,14 +23,15 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
2323 . iter ( )
2424 . map ( |f| should_inline ( & disallowed_argument_types, & disallowed_return_types, f) )
2525 . collect ( ) ;
26- // This algorithm gets real sad if there's recursion - but, good news, SPIR-V bans recursion
27- let postorder = compute_function_postorder ( sess , module , & to_delete ) ? ;
28- let functions = module
26+ // This algorithm gets real sad if there's recursion - but, good news, SPIR-V bans recursion,
27+ // so we exit with an error if [` compute_function_postorder`] finds it.
28+ let function_to_index = module
2929 . functions
3030 . iter ( )
3131 . enumerate ( )
3232 . map ( |( idx, f) | ( f. def_id ( ) . unwrap ( ) , idx) )
3333 . collect ( ) ;
34+ let postorder = compute_function_postorder ( sess, module, & function_to_index, & to_delete) ?;
3435 let void = module
3536 . types_global_values
3637 . iter ( )
@@ -56,10 +57,13 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
5657 types_global_values : & mut module. types_global_values ,
5758 void,
5859 ptr_map,
59- functions : & functions ,
60+ function_to_index : & function_to_index ,
6061 needs_inline : & to_delete,
6162 invalid_args,
6263 } ;
64+ // Processing functions in post-order of call tree we ensure that
65+ // inlined functions already have all of the inner functions inlined, so we don't do
66+ // the same work multiple times.
6367 for index in postorder {
6468 inliner. inline_fn ( & mut module. functions , index) ;
6569 fuse_trivial_branches ( & mut module. functions [ index] ) ;
@@ -87,14 +91,9 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
8791fn compute_function_postorder (
8892 sess : & Session ,
8993 module : & Module ,
94+ func_to_index : & FxHashMap < Word , usize > ,
9095 to_delete : & [ bool ] ,
9196) -> super :: Result < Vec < usize > > {
92- let func_to_index: FxHashMap < Word , usize > = module
93- . functions
94- . iter ( )
95- . enumerate ( )
96- . map ( |( index, func) | ( func. def_id ( ) . unwrap ( ) , index) )
97- . collect ( ) ;
9897 /// Possible node states for cycle-discovering DFS.
9998 #[ derive( Clone , PartialEq ) ]
10099 enum NodeState {
@@ -286,7 +285,7 @@ struct Inliner<'m, 'map> {
286285 types_global_values : & ' m mut Vec < Instruction > ,
287286 void : Word ,
288287 ptr_map : FxHashMap < Word , Word > ,
289- functions : & ' map FunctionMap ,
288+ function_to_index : & ' map FunctionMap ,
290289 needs_inline : & ' map [ bool ] ,
291290 invalid_args : FxHashSet < Word > ,
292291}
@@ -330,14 +329,9 @@ impl Inliner<'_, '_> {
330329 functions[ index] = function;
331330 }
332331
333- /// Inlines one block and returns whether inlining actually occurred .
332+ /// Inlines one block.
334333 /// After calling this, `blocks[block_idx]` is finished processing.
335- fn inline_block (
336- & mut self ,
337- caller : & mut Function ,
338- functions : & [ Function ] ,
339- block_idx : usize ,
340- ) -> bool {
334+ fn inline_block ( & mut self , caller : & mut Function , functions : & [ Function ] , block_idx : usize ) {
341335 // Find the first inlined OpFunctionCall
342336 let call = caller. blocks [ block_idx]
343337 . instructions
@@ -348,14 +342,14 @@ impl Inliner<'_, '_> {
348342 (
349343 index,
350344 inst,
351- self . functions [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
345+ self . function_to_index [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
352346 )
353347 } )
354348 . find ( |( _, inst, func_idx) | {
355349 self . needs_inline [ * func_idx] || args_invalid ( & self . invalid_args , inst)
356350 } ) ;
357351 let ( call_index, call_inst, callee_idx) = match call {
358- None => return false ,
352+ None => return ,
359353 Some ( call) => call,
360354 } ;
361355 let callee = & functions[ callee_idx] ;
@@ -424,7 +418,8 @@ impl Inliner<'_, '_> {
424418 let mut callee_header = take ( & mut inlined_blocks[ 0 ] ) . instructions ;
425419 // TODO: OpLine handling
426420 let num_variables = callee_header. partition_point ( |inst| inst. class . opcode == Op :: Variable ) ;
427- // Rather than fuse blocks, generate a new jump here. Branch fusing will take care of
421+ // Rather than fuse the first block of the inline function to the current block,
422+ // generate a new jump here. Branch fusing will take care of
428423 // it, and we maintain the invariant that current block has finished processing.
429424 let jump_to = self . id ( ) ;
430425 inlined_blocks[ 0 ] = Block {
@@ -465,8 +460,6 @@ impl Inliner<'_, '_> {
465460 caller
466461 . blocks
467462 . splice ( ( block_idx + 1 ) ..( block_idx + 1 ) , inlined_blocks) ;
468-
469- true
470463 }
471464
472465 fn add_clone_id_rules ( & mut self , rewrite_rules : & mut FxHashMap < Word , Word > , blocks : & [ Block ] ) {
0 commit comments