mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-29 16:40:13 +01:00
nak: Break guts of liveness into traits
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24998>
This commit is contained in:
parent
f1cb99d06b
commit
71c5bbc5a8
2 changed files with 60 additions and 41 deletions
|
|
@ -8,7 +8,7 @@
|
|||
use crate::bitset::BitSet;
|
||||
use crate::nak_cfg::CFG;
|
||||
use crate::nak_ir::*;
|
||||
use crate::nak_liveness::{BlockLiveness, Liveness};
|
||||
use crate::nak_liveness::{BlockLiveness, Liveness, NextUseLiveness};
|
||||
use crate::util::NextMultipleOf;
|
||||
|
||||
use std::cmp::{max, Ordering};
|
||||
|
|
@ -878,10 +878,10 @@ impl AssignRegsBlock {
|
|||
}
|
||||
}
|
||||
|
||||
fn first_pass(
|
||||
fn first_pass<BL: BlockLiveness>(
|
||||
&mut self,
|
||||
b: &mut BasicBlock,
|
||||
bl: &BlockLiveness,
|
||||
bl: &BL,
|
||||
pred_ra: Option<&PerRegFile<RegAllocator>>,
|
||||
) {
|
||||
/* Populate live in from the register file we're handed. We'll add more
|
||||
|
|
@ -910,13 +910,13 @@ impl AssignRegsBlock {
|
|||
/* Build up the kill set */
|
||||
killed.clear();
|
||||
if let PredRef::SSA(ssa) = &instr.pred.pred_ref {
|
||||
if !bl.is_live_after(ssa, ip) {
|
||||
if !bl.is_live_after_ip(ssa, ip) {
|
||||
killed.insert(*ssa);
|
||||
}
|
||||
}
|
||||
for src in instr.srcs() {
|
||||
for ssa in src.iter_ssa() {
|
||||
if !bl.is_live_after(ssa, ip) {
|
||||
if !bl.is_live_after_ip(ssa, ip) {
|
||||
killed.insert(*ssa);
|
||||
}
|
||||
}
|
||||
|
|
@ -984,7 +984,7 @@ impl AssignRegs {
|
|||
|
||||
pub fn run(&mut self, f: &mut Function) {
|
||||
let cfg = CFG::for_function(f);
|
||||
let live = Liveness::for_function(f, &cfg);
|
||||
let live = NextUseLiveness::for_function(f, &cfg);
|
||||
|
||||
let num_regs = PerRegFile::new_with(|file| {
|
||||
let num_regs = file.num_regs(self.sm);
|
||||
|
|
@ -1003,7 +1003,7 @@ impl AssignRegs {
|
|||
});
|
||||
|
||||
for b in &mut f.blocks {
|
||||
let bl = live.block(&b);
|
||||
let bl = live.block_live(b.id);
|
||||
|
||||
let pred = cfg.block_predecessors(b.id);
|
||||
let pred_ra = if pred.is_empty() {
|
||||
|
|
@ -1014,7 +1014,7 @@ impl AssignRegs {
|
|||
};
|
||||
|
||||
let mut arb = AssignRegsBlock::new(&num_regs);
|
||||
arb.first_pass(b, &bl, pred_ra);
|
||||
arb.first_pass(b, bl, pred_ra);
|
||||
self.blocks.insert(b.id, arb);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,28 @@
|
|||
use crate::nak_cfg::CFG;
|
||||
use crate::nak_ir::*;
|
||||
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::max;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
struct SSAEntry {
|
||||
pub trait BlockLiveness {
|
||||
fn is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool;
|
||||
fn is_live_in(&self, val: &SSAValue) -> bool;
|
||||
fn is_live_out(&self, val: &SSAValue) -> bool;
|
||||
}
|
||||
|
||||
pub trait Liveness {
|
||||
type PerBlock: BlockLiveness;
|
||||
|
||||
fn block_live(&self, id: u32) -> &Self::PerBlock;
|
||||
}
|
||||
|
||||
struct SSAUseDef {
|
||||
defined: bool,
|
||||
uses: Vec<usize>,
|
||||
}
|
||||
|
||||
impl SSAEntry {
|
||||
impl SSAUseDef {
|
||||
fn add_def(&mut self) {
|
||||
self.defined = true;
|
||||
}
|
||||
|
|
@ -51,15 +63,15 @@ impl SSAEntry {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct BlockLiveness {
|
||||
pub struct NextUseBlockLiveness {
|
||||
num_instrs: usize,
|
||||
ssa_map: HashMap<SSAValue, SSAEntry>,
|
||||
ssa_map: HashMap<SSAValue, SSAUseDef>,
|
||||
max_live: PerRegFile<u32>,
|
||||
}
|
||||
|
||||
impl BlockLiveness {
|
||||
fn entry_mut(&mut self, ssa: SSAValue) -> &mut SSAEntry {
|
||||
self.ssa_map.entry(ssa).or_insert_with(|| SSAEntry {
|
||||
impl NextUseBlockLiveness {
|
||||
fn entry_mut(&mut self, ssa: SSAValue) -> &mut SSAUseDef {
|
||||
self.ssa_map.entry(ssa).or_insert_with(|| SSAUseDef {
|
||||
defined: false,
|
||||
uses: Vec::new(),
|
||||
})
|
||||
|
|
@ -99,8 +111,10 @@ impl BlockLiveness {
|
|||
pub fn max_live(&self, file: RegFile) -> u32 {
|
||||
self.max_live[file]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_live_after(&self, val: &SSAValue, ip: usize) -> bool {
|
||||
impl BlockLiveness for NextUseBlockLiveness {
|
||||
fn is_live_after_ip(&self, val: &SSAValue, ip: usize) -> bool {
|
||||
if let Some(entry) = self.ssa_map.get(val) {
|
||||
if let Some(last_use_ip) = entry.uses.last() {
|
||||
*last_use_ip > ip
|
||||
|
|
@ -112,8 +126,7 @@ impl BlockLiveness {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_live_in(&self, val: &SSAValue) -> bool {
|
||||
fn is_live_in(&self, val: &SSAValue) -> bool {
|
||||
if let Some(entry) = self.ssa_map.get(val) {
|
||||
!entry.defined && !entry.uses.is_empty()
|
||||
} else {
|
||||
|
|
@ -121,8 +134,7 @@ impl BlockLiveness {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_live_out(&self, val: &SSAValue) -> bool {
|
||||
fn is_live_out(&self, val: &SSAValue) -> bool {
|
||||
if let Some(entry) = self.ssa_map.get(val) {
|
||||
if let Some(last_use_ip) = entry.uses.last() {
|
||||
*last_use_ip >= self.num_instrs
|
||||
|
|
@ -135,29 +147,21 @@ impl BlockLiveness {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Liveness {
|
||||
blocks: HashMap<u32, RefCell<BlockLiveness>>,
|
||||
pub struct NextUseLiveness {
|
||||
blocks: HashMap<u32, NextUseBlockLiveness>,
|
||||
max_live: PerRegFile<u32>,
|
||||
}
|
||||
|
||||
impl Liveness {
|
||||
pub fn block(&self, block: &BasicBlock) -> Ref<BlockLiveness> {
|
||||
self.blocks.get(&block.id).unwrap().borrow()
|
||||
}
|
||||
|
||||
impl NextUseLiveness {
|
||||
pub fn max_live(&self, file: RegFile) -> u32 {
|
||||
self.max_live[file]
|
||||
}
|
||||
|
||||
pub fn for_function(func: &Function, cfg: &CFG) -> Liveness {
|
||||
let mut l = Liveness {
|
||||
blocks: HashMap::new(),
|
||||
max_live: Default::default(),
|
||||
};
|
||||
|
||||
pub fn for_function(func: &Function, cfg: &CFG) -> NextUseLiveness {
|
||||
let mut blocks = HashMap::new();
|
||||
for b in &func.blocks {
|
||||
let bl = BlockLiveness::for_block(b);
|
||||
l.blocks.insert(b.id, RefCell::new(bl));
|
||||
let bl = NextUseBlockLiveness::for_block(b);
|
||||
blocks.insert(b.id, RefCell::new(bl));
|
||||
}
|
||||
|
||||
let mut to_do = true;
|
||||
|
|
@ -165,7 +169,7 @@ impl Liveness {
|
|||
to_do = false;
|
||||
for b in func.blocks.iter().rev() {
|
||||
let num_instrs = b.instrs.len();
|
||||
let mut bl = l.blocks.get(&b.id).unwrap().borrow_mut();
|
||||
let mut bl = blocks.get(&b.id).unwrap().borrow_mut();
|
||||
|
||||
/* Compute live-out */
|
||||
for sb_id in cfg.block_successors(b.id) {
|
||||
|
|
@ -183,7 +187,7 @@ impl Liveness {
|
|||
.add_successor_use(num_instrs, *first_use_ip);
|
||||
}
|
||||
} else {
|
||||
let sbl = l.blocks.get(&sb_id).unwrap().borrow();
|
||||
let sbl = blocks.get(&sb_id).unwrap().borrow();
|
||||
for (ssa, entry) in sbl.ssa_map.iter() {
|
||||
if entry.defined {
|
||||
continue;
|
||||
|
|
@ -202,8 +206,15 @@ impl Liveness {
|
|||
}
|
||||
}
|
||||
|
||||
let mut l = NextUseLiveness {
|
||||
blocks: HashMap::from_iter(
|
||||
blocks.drain().map(|(k, v)| (k, v.into_inner())),
|
||||
),
|
||||
max_live: Default::default(),
|
||||
};
|
||||
|
||||
for b in func.blocks.iter().rev() {
|
||||
let mut bl = l.blocks.get(&b.id).unwrap().borrow_mut();
|
||||
let bl = l.blocks.get_mut(&b.id).unwrap();
|
||||
|
||||
/* Populate a live set based on live out */
|
||||
let mut dead = HashSet::new();
|
||||
|
|
@ -236,7 +247,7 @@ impl Liveness {
|
|||
dead.clear();
|
||||
|
||||
if let PredRef::SSA(ssa) = &instr.pred.pred_ref {
|
||||
if !bl.is_live_after(ssa, ip) {
|
||||
if !bl.is_live_after_ip(ssa, ip) {
|
||||
dead.insert(*ssa);
|
||||
}
|
||||
}
|
||||
|
|
@ -244,7 +255,7 @@ impl Liveness {
|
|||
for src in instr.srcs() {
|
||||
if let SrcRef::SSA(vec) = &src.src_ref {
|
||||
for ssa in vec.iter() {
|
||||
if !bl.is_live_after(ssa, ip) {
|
||||
if !bl.is_live_after_ip(ssa, ip) {
|
||||
dead.insert(*ssa);
|
||||
}
|
||||
}
|
||||
|
|
@ -273,3 +284,11 @@ impl Liveness {
|
|||
l
|
||||
}
|
||||
}
|
||||
|
||||
impl Liveness for NextUseLiveness {
|
||||
type PerBlock = NextUseBlockLiveness;
|
||||
|
||||
fn block_live(&self, id: u32) -> &NextUseBlockLiveness {
|
||||
self.blocks.get(&id).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue