@@ -23,14 +23,15 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
23
23
. iter ( )
24
24
. map ( |f| should_inline ( & disallowed_argument_types, & disallowed_return_types, f) )
25
25
. 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
29
29
. functions
30
30
. iter ( )
31
31
. enumerate ( )
32
32
. map ( |( idx, f) | ( f. def_id ( ) . unwrap ( ) , idx) )
33
33
. collect ( ) ;
34
+ let postorder = compute_function_postorder ( sess, module, & function_to_index, & to_delete) ?;
34
35
let void = module
35
36
. types_global_values
36
37
. iter ( )
@@ -56,10 +57,13 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
56
57
types_global_values : & mut module. types_global_values ,
57
58
void,
58
59
ptr_map,
59
- functions : & functions ,
60
+ function_to_index : & function_to_index ,
60
61
needs_inline : & to_delete,
61
62
invalid_args,
62
63
} ;
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.
63
67
for index in postorder {
64
68
inliner. inline_fn ( & mut module. functions , index) ;
65
69
fuse_trivial_branches ( & mut module. functions [ index] ) ;
@@ -87,14 +91,9 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
87
91
fn compute_function_postorder (
88
92
sess : & Session ,
89
93
module : & Module ,
94
+ func_to_index : & FxHashMap < Word , usize > ,
90
95
to_delete : & [ bool ] ,
91
96
) -> 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 ( ) ;
98
97
/// Possible node states for cycle-discovering DFS.
99
98
#[ derive( Clone , PartialEq ) ]
100
99
enum NodeState {
@@ -286,7 +285,7 @@ struct Inliner<'m, 'map> {
286
285
types_global_values : & ' m mut Vec < Instruction > ,
287
286
void : Word ,
288
287
ptr_map : FxHashMap < Word , Word > ,
289
- functions : & ' map FunctionMap ,
288
+ function_to_index : & ' map FunctionMap ,
290
289
needs_inline : & ' map [ bool ] ,
291
290
invalid_args : FxHashSet < Word > ,
292
291
}
@@ -330,14 +329,9 @@ impl Inliner<'_, '_> {
330
329
functions[ index] = function;
331
330
}
332
331
333
- /// Inlines one block and returns whether inlining actually occurred .
332
+ /// Inlines one block.
334
333
/// 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 ) {
341
335
// Find the first inlined OpFunctionCall
342
336
let call = caller. blocks [ block_idx]
343
337
. instructions
@@ -348,14 +342,14 @@ impl Inliner<'_, '_> {
348
342
(
349
343
index,
350
344
inst,
351
- self . functions [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
345
+ self . function_to_index [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
352
346
)
353
347
} )
354
348
. find ( |( _, inst, func_idx) | {
355
349
self . needs_inline [ * func_idx] || args_invalid ( & self . invalid_args , inst)
356
350
} ) ;
357
351
let ( call_index, call_inst, callee_idx) = match call {
358
- None => return false ,
352
+ None => return ,
359
353
Some ( call) => call,
360
354
} ;
361
355
let callee = & functions[ callee_idx] ;
@@ -424,7 +418,8 @@ impl Inliner<'_, '_> {
424
418
let mut callee_header = take ( & mut inlined_blocks[ 0 ] ) . instructions ;
425
419
// TODO: OpLine handling
426
420
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
428
423
// it, and we maintain the invariant that current block has finished processing.
429
424
let jump_to = self . id ( ) ;
430
425
inlined_blocks[ 0 ] = Block {
@@ -465,8 +460,6 @@ impl Inliner<'_, '_> {
465
460
caller
466
461
. blocks
467
462
. splice ( ( block_idx + 1 ) ..( block_idx + 1 ) , inlined_blocks) ;
468
-
469
- true
470
463
}
471
464
472
465
fn add_clone_id_rules ( & mut self , rewrite_rules : & mut FxHashMap < Word , Word > , blocks : & [ Block ] ) {
0 commit comments