From 4e95cb908f58ce29d61c123db793f2d76404b05f Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 30 Jan 2023 20:53:16 -0600 Subject: [PATCH] nak: Add a dead-code pass Part-of: --- src/nouveau/compiler/nak.rs | 5 ++ src/nouveau/compiler/nak_ir.rs | 7 +++ src/nouveau/compiler/nak_opt_dce.rs | 86 +++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 src/nouveau/compiler/nak_opt_dce.rs diff --git a/src/nouveau/compiler/nak.rs b/src/nouveau/compiler/nak.rs index 27ebfcea4f5..a20e9a17d79 100644 --- a/src/nouveau/compiler/nak.rs +++ b/src/nouveau/compiler/nak.rs @@ -6,6 +6,7 @@ mod nak_from_nir; mod nak_ir; mod nak_opt_copy_prop; +mod nak_opt_dce; mod nir; use nak_bindings::*; @@ -40,5 +41,9 @@ pub extern "C" fn nak_compile_shader( println!("NAK IR:\n{}", &s); + s.opt_dce(); + + println!("NAK IR:\n{}", &s); + std::ptr::null_mut() } diff --git a/src/nouveau/compiler/nak_ir.rs b/src/nouveau/compiler/nak_ir.rs index 2d104c0da55..f6f52d1c4ed 100644 --- a/src/nouveau/compiler/nak_ir.rs +++ b/src/nouveau/compiler/nak_ir.rs @@ -595,6 +595,13 @@ impl Instr { pub fn num_srcs(&self) -> usize { self.srcs().len() } + + pub fn can_eliminate(&self) -> bool { + match self.op { + Opcode::FS_OUT | Opcode::EXIT | Opcode::AST(_) => false, + _ => true, + } + } } pub struct MetaInstr { diff --git a/src/nouveau/compiler/nak_opt_dce.rs b/src/nouveau/compiler/nak_opt_dce.rs new file mode 100644 index 00000000000..3b994342721 --- /dev/null +++ b/src/nouveau/compiler/nak_opt_dce.rs @@ -0,0 +1,86 @@ +/* + * Copyright © 2022 Collabora, Ltd. + * SPDX-License-Identifier: MIT + */ + +use crate::nak_ir::*; + +use std::collections::HashSet; + +struct DeadCodePass { + live_ssa: HashSet, +} + +impl DeadCodePass { + pub fn new() -> DeadCodePass { + DeadCodePass { + live_ssa: HashSet::new(), + } + } + + fn mark_ssa_live(&mut self, ssa: &SSAValue) { + self.live_ssa.insert(*ssa); + } + + fn mark_instr_live(&mut self, instr: &Instr) { + for src in instr.srcs() { + if let Src::SSA(ssa) = src { + self.mark_ssa_live(ssa); + } + } + } + + fn is_dst_live(&self, dst: &Dst) -> bool { + match dst { + Ref::SSA(ssa) => self.live_ssa.get(ssa).is_some(), + Ref::Zero => false, + _ => panic!("Invalid SSA destination"), + } + } + + fn is_instr_live(&self, instr: &Instr) -> bool { + if !instr.can_eliminate() { + return true; + } + + for dst in instr.dsts() { + if self.is_dst_live(dst) { + return true; + } + } + + false + } + + pub fn run(&mut self, f: &mut Function) { + let mut has_any_dead = false; + + for b in f.blocks.iter().rev() { + for instr in b.instrs.iter().rev() { + if self.is_instr_live(instr) { + self.mark_instr_live(instr); + } else { + has_any_dead = true; + } + } + } + + if has_any_dead { + f.map_instrs(&|instr: Instr| -> Instr { + if self.is_instr_live(&instr) { + instr + } else { + Instr::new_noop() + } + }) + } + } +} + +impl Shader { + pub fn opt_dce(&mut self) { + for f in &mut self.functions { + DeadCodePass::new().run(f); + } + } +}