@@ -38,7 +38,6 @@ pub type Result<T> = std::result::Result<T, ErrorGuaranteed>;
3838#[ derive( Default ) ]
3939pub struct Options {
4040 pub compact_ids : bool ,
41- pub dce : bool ,
4241 pub early_report_zombies : bool ,
4342 pub infer_storage_classes : bool ,
4443 pub structurize : bool ,
@@ -272,6 +271,13 @@ pub fn link(
272271 output
273272 } ;
274273
274+ // FIXME(eddyb) do this before ever saving the original `.spv`s to disk.
275+ {
276+ let _timer = sess. timer ( "link_dce-post-merge" ) ;
277+ dce:: dce ( & mut output) ;
278+ }
279+
280+ // HACK(eddyb) this has to be after DCE, to not break SPIR-T w/ dead decorations.
275281 if let Some ( dir) = & opts. dump_post_merge {
276282 dump_spv_and_spirt ( & output, dir. join ( disambiguated_crate_name_for_dumps) ) ;
277283 }
@@ -292,6 +298,11 @@ pub fn link(
292298 import_export_link:: run ( opts, sess, & mut output) ?;
293299 }
294300
301+ {
302+ let _timer = sess. timer ( "link_dce-post-link" ) ;
303+ dce:: dce ( & mut output) ;
304+ }
305+
295306 {
296307 let _timer = sess. timer ( "link_fragment_inst_check" ) ;
297308 simple_passes:: check_fragment_insts ( sess, & output) ?;
@@ -306,29 +317,11 @@ pub fn link(
306317 }
307318
308319 if opts. early_report_zombies {
309- // HACK(eddyb) `report_and_remove_zombies` is bad at determining whether
310- // some things are dead (such as whole blocks), and there's no reason to
311- // *not* run DCE, given SPIR-T exists and makes DCE mandatory, but we're
312- // still only going to do the minimum necessary ("block ordering").
313- {
314- let _timer = sess. timer ( "link_block_ordering_pass-before-report_and_remove_zombies" ) ;
315- for func in & mut output. functions {
316- simple_passes:: block_ordering_pass ( func) ;
317- }
318- }
319-
320320 let _timer = sess. timer ( "link_report_and_remove_zombies" ) ;
321321 zombies:: report_and_remove_zombies ( sess, & mut output) ?;
322322 }
323323
324324 if opts. infer_storage_classes {
325- // HACK(eddyb) this is not the best approach, but storage class inference
326- // can still fail in entirely legitimate ways (i.e. mismatches in zombies).
327- if !opts. early_report_zombies {
328- let _timer = sess. timer ( "link_dce-before-specialize_generic_storage_class" ) ;
329- dce:: dce ( & mut output) ;
330- }
331-
332325 let _timer = sess. timer ( "specialize_generic_storage_class" ) ;
333326 // HACK(eddyb) `specializer` requires functions' blocks to be in RPO order
334327 // (i.e. `block_ordering_pass`) - this could be relaxed by using RPO visit
@@ -361,7 +354,7 @@ pub fn link(
361354
362355 // NOTE(eddyb) with SPIR-T, we can do `mem2reg` before inlining, too!
363356 {
364- if opts . dce {
357+ {
365358 let _timer = sess. timer ( "link_dce-before-inlining" ) ;
366359 dce:: dce ( & mut output) ;
367360 }
@@ -404,13 +397,14 @@ pub fn link(
404397 }
405398 }
406399
407- if opts . dce {
400+ {
408401 let _timer =
409402 sess. timer ( "link_dce-and-remove_duplicate_debuginfo-after-mem2reg-before-inlining" ) ;
410403 dce:: dce ( & mut output) ;
411404 duplicates:: remove_duplicate_debuginfo ( & mut output) ;
412405 }
413406
407+ // HACK(eddyb) this has to be after DCE, to not break SPIR-T w/ dead decorations.
414408 if let Some ( dir) = & opts. dump_pre_inline {
415409 dump_spv_and_spirt ( & output, dir. join ( disambiguated_crate_name_for_dumps) ) ;
416410 }
@@ -420,7 +414,7 @@ pub fn link(
420414 inline:: inline ( sess, & mut output) ?;
421415 }
422416
423- if opts . dce {
417+ {
424418 let _timer = sess. timer ( "link_dce-after-inlining" ) ;
425419 dce:: dce ( & mut output) ;
426420 }
@@ -469,7 +463,7 @@ pub fn link(
469463 }
470464 }
471465
472- if opts . dce {
466+ {
473467 let _timer =
474468 sess. timer ( "link_dce-and-remove_duplicate_debuginfo-after-mem2reg-after-inlining" ) ;
475469 dce:: dce ( & mut output) ;
@@ -711,6 +705,15 @@ pub fn link(
711705 ) ,
712706 } ;
713707 for ( file_stem, output) in output_module_iter {
708+ // Run DCE again, even if module_output_type == ModuleOutputType::Multiple - the first DCE ran before
709+ // structurization and mem2reg (for perf reasons), and mem2reg may remove references to
710+ // invalid types, so we need to DCE again.
711+ {
712+ let _timer = sess. timer ( "link_dce-post-split" ) ;
713+ dce:: dce ( output) ;
714+ }
715+
716+ // HACK(eddyb) this has to be after DCE, to not break SPIR-T w/ dead decorations.
714717 if let Some ( dir) = & opts. dump_post_split {
715718 let mut file_name = disambiguated_crate_name_for_dumps. to_os_string ( ) ;
716719 if let Some ( file_stem) = file_stem {
@@ -720,13 +723,6 @@ pub fn link(
720723
721724 dump_spv_and_spirt ( output, dir. join ( file_name) ) ;
722725 }
723- // Run DCE again, even if module_output_type == ModuleOutputType::Multiple - the first DCE ran before
724- // structurization and mem2reg (for perf reasons), and mem2reg may remove references to
725- // invalid types, so we need to DCE again.
726- if opts. dce {
727- let _timer = sess. timer ( "link_dce_2" ) ;
728- dce:: dce ( output) ;
729- }
730726
731727 {
732728 let _timer = sess. timer ( "link_remove_duplicate_debuginfo" ) ;
0 commit comments