Skip to content

Commit 6aeec0b

Browse files
committed
linker: make DCE mandatory and run it very early on, as well.
1 parent f8067e1 commit 6aeec0b

File tree

4 files changed

+27
-40
lines changed

4 files changed

+27
-40
lines changed

crates/rustc_codegen_spirv/src/codegen_cx/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ impl CodegenArgs {
397397
// FIXME(eddyb) should these be handled as `-C linker-args="..."` instead?
398398
{
399399
// FIXME(eddyb) clean up this `no-` "negation prefix" situation.
400-
opts.optflag("", "no-dce", "disables running dead code elimination");
401400
opts.optflag(
402401
"",
403402
"no-compact-ids",
@@ -604,7 +603,6 @@ impl CodegenArgs {
604603
// FIXME(eddyb) should these be handled as `-C linker-args="..."` instead?
605604
let linker_opts = crate::linker::Options {
606605
// FIXME(eddyb) clean up this `no-` "negation prefix" situation.
607-
dce: !matches.opt_present("no-dce"),
608606
compact_ids: !matches.opt_present("no-compact-ids"),
609607
early_report_zombies: !matches.opt_present("no-early-report-zombies"),
610608
infer_storage_classes: !matches.opt_present("no-infer-storage-classes"),

crates/rustc_codegen_spirv/src/linker/mod.rs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub type Result<T> = std::result::Result<T, ErrorGuaranteed>;
3838
#[derive(Default)]
3939
pub 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");

crates/rustc_codegen_spirv/src/linker/test.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ fn assemble_and_link(binaries: &[&[u8]]) -> Result<Module, PrettyString> {
7070
binaries,
7171
&crate::linker::Options {
7272
compact_ids: true,
73-
dce: true,
7473
keep_link_exports: true,
7574
..Default::default()
7675
},

docs/src/codegen-args.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ Dumps the module, to a file in `DIR`, immediately after the inliner pass runs.
8989

9090
### `--dump-post-split DIR`
9191

92-
Dumps the modules, to files in `DIR`, immediately after multimodule splitting, but before final cleanup passes (e.g.
93-
DCE to remove the other entry points).
92+
Dumps the modules, to files in `DIR`, immediately after multimodule splitting.
9493

9594
### `--dump-post-link DIR`
9695

@@ -113,11 +112,6 @@ Disables running `spirv-val` on the final output. Spooky scary option, can cause
113112

114113
Forcibly disables running `spirv-opt` on the final output, even if optimizations are enabled.
115114

116-
### `--no-dce`
117-
118-
Disables running dead code elimination. Can and probably will generate invalid modules or crash the
119-
linker, hasn't been tested for a while.
120-
121115
### `--no-compact-ids`
122116

123117
Disables compaction of SPIR-V IDs at the end of linking. Causes absolutely ginormous IDs to be

0 commit comments

Comments
 (0)