@@ -24,14 +24,15 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
24
24
. iter ( )
25
25
. map ( |f| should_inline ( & disallowed_argument_types, & disallowed_return_types, f) )
26
26
. collect ( ) ;
27
- // This algorithm gets real sad if there's recursion - but, good news, SPIR-V bans recursion
28
- let postorder = compute_function_postorder ( sess , module , & to_delete ) ? ;
29
- let functions = module
27
+ // This algorithm gets real sad if there's recursion - but, good news, SPIR-V bans recursion,
28
+ // so we exit with an error if [` compute_function_postorder`] finds it.
29
+ let function_to_index = module
30
30
. functions
31
31
. iter ( )
32
32
. enumerate ( )
33
33
. map ( |( idx, f) | ( f. def_id ( ) . unwrap ( ) , idx) )
34
34
. collect ( ) ;
35
+ let postorder = compute_function_postorder ( sess, module, & function_to_index, & to_delete) ?;
35
36
let void = module
36
37
. types_global_values
37
38
. 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 {
@@ -284,7 +283,7 @@ struct Inliner<'m, 'map> {
284
283
types_global_values : & ' m mut Vec < Instruction > ,
285
284
void : Word ,
286
285
ptr_map : FxHashMap < Word , Word > ,
287
- functions : & ' map FunctionMap ,
286
+ function_to_index : & ' map FunctionMap ,
288
287
needs_inline : & ' map [ bool ] ,
289
288
invalid_args : FxHashSet < Word > ,
290
289
}
@@ -328,14 +327,9 @@ impl Inliner<'_, '_> {
328
327
functions[ index] = function;
329
328
}
330
329
331
- /// Inlines one block and returns whether inlining actually occurred .
330
+ /// Inlines one block.
332
331
/// After calling this, `blocks[block_idx]` is finished processing.
333
- fn inline_block (
334
- & mut self ,
335
- caller : & mut Function ,
336
- functions : & [ Function ] ,
337
- block_idx : usize ,
338
- ) -> bool {
332
+ fn inline_block ( & mut self , caller : & mut Function , functions : & [ Function ] , block_idx : usize ) {
339
333
// Find the first inlined OpFunctionCall
340
334
let call = caller. blocks [ block_idx]
341
335
. instructions
@@ -346,14 +340,14 @@ impl Inliner<'_, '_> {
346
340
(
347
341
index,
348
342
inst,
349
- self . functions [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
343
+ self . function_to_index [ & inst. operands [ 0 ] . id_ref_any ( ) . unwrap ( ) ] ,
350
344
)
351
345
} )
352
346
. find ( |( _, inst, func_idx) | {
353
347
self . needs_inline [ * func_idx] || args_invalid ( & self . invalid_args , inst)
354
348
} ) ;
355
349
let ( call_index, call_inst, callee_idx) = match call {
356
- None => return false ,
350
+ None => return ,
357
351
Some ( call) => call,
358
352
} ;
359
353
let callee = & functions[ callee_idx] ;
@@ -422,7 +416,8 @@ impl Inliner<'_, '_> {
422
416
let mut callee_header = take ( & mut inlined_blocks[ 0 ] ) . instructions ;
423
417
// TODO: OpLine handling
424
418
let num_variables = callee_header. partition_point ( |inst| inst. class . opcode == Op :: Variable ) ;
425
- // Rather than fuse blocks, generate a new jump here. Branch fusing will take care of
419
+ // Rather than fuse the first block of the inline function to the current block,
420
+ // generate a new jump here. Branch fusing will take care of
426
421
// it, and we maintain the invariant that current block has finished processing.
427
422
let jump_to = self . id ( ) ;
428
423
inlined_blocks[ 0 ] = Block {
@@ -463,8 +458,6 @@ impl Inliner<'_, '_> {
463
458
caller
464
459
. blocks
465
460
. splice ( ( block_idx + 1 ) ..( block_idx + 1 ) , inlined_blocks) ;
466
-
467
- true
468
461
}
469
462
470
463
fn add_clone_id_rules ( & mut self , rewrite_rules : & mut FxHashMap < Word , Word > , blocks : & [ Block ] ) {
0 commit comments