nak: protect static cycle counting against overflows
Now with the loop aware cycle counting it's very likely that we'll overflow an u32 when counting, so do the counting in u64. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36528>
This commit is contained in:
@@ -146,7 +146,7 @@ struct nak_shader_info {
|
||||
uint32_t num_instrs;
|
||||
|
||||
/** Number of cycles used by fixed-latency instructions */
|
||||
uint32_t num_static_cycles;
|
||||
uint64_t num_static_cycles;
|
||||
|
||||
/** Number of spills from GPRs to Memory */
|
||||
uint32_t num_spills_to_mem;
|
||||
@@ -211,6 +211,8 @@ struct nak_shader_info {
|
||||
struct nak_xfb_info xfb;
|
||||
} vtg;
|
||||
|
||||
uint8_t _pad1[4];
|
||||
|
||||
/** Shader header for 3D stages */
|
||||
uint32_t hdr[32];
|
||||
};
|
||||
|
||||
@@ -266,6 +266,7 @@ impl ShaderBin {
|
||||
},
|
||||
num_control_barriers: info.num_control_barriers,
|
||||
_pad0: Default::default(),
|
||||
_pad1: Default::default(),
|
||||
max_warps_per_sm: info.max_warps_per_sm,
|
||||
num_instrs: info.num_instrs,
|
||||
num_static_cycles: info.num_static_cycles,
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::reg_tracker::RegTracker;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::cmp::max;
|
||||
use std::ops::Range;
|
||||
use std::{slice, u32, u8};
|
||||
use std::{slice, u8};
|
||||
|
||||
#[derive(Clone)]
|
||||
enum RegUse<T: Clone> {
|
||||
@@ -670,7 +670,7 @@ fn assign_barriers(f: &mut Function, sm: &dyn ShaderModel) {
|
||||
}
|
||||
}
|
||||
|
||||
fn calc_delays(f: &mut Function, sm: &dyn ShaderModel) -> u32 {
|
||||
fn calc_delays(f: &mut Function, sm: &dyn ShaderModel) -> u64 {
|
||||
let mut min_num_static_cycles = 0;
|
||||
for i in (0..f.blocks.len()).rev() {
|
||||
let b = &mut f.blocks[i];
|
||||
@@ -784,7 +784,12 @@ fn calc_delays(f: &mut Function, sm: &dyn ShaderModel) -> u32 {
|
||||
cycle = min_start;
|
||||
}
|
||||
|
||||
min_num_static_cycles += cycle * estimate_block_weight(&f.blocks, i);
|
||||
let block_weight = estimate_block_weight(&f.blocks, i);
|
||||
min_num_static_cycles = u64::from(cycle)
|
||||
.checked_mul(block_weight)
|
||||
.expect("Cycle count estimate overflow")
|
||||
.checked_add(min_num_static_cycles)
|
||||
.expect("Cycle count estimate overflow");
|
||||
}
|
||||
|
||||
let max_instr_delay = sm.max_instr_delay();
|
||||
@@ -861,7 +866,7 @@ impl Shader<'_> {
|
||||
if DEBUG.serial() {
|
||||
self.assign_deps_serial();
|
||||
} else {
|
||||
let mut min_num_static_cycles = 0;
|
||||
let mut min_num_static_cycles = 0u64;
|
||||
for f in &mut self.functions {
|
||||
assign_barriers(f, self.sm);
|
||||
min_num_static_cycles += calc_delays(f, self.sm);
|
||||
|
||||
@@ -8970,7 +8970,7 @@ pub struct ShaderInfo {
|
||||
pub num_gprs: u8,
|
||||
pub num_control_barriers: u8,
|
||||
pub num_instrs: u32,
|
||||
pub num_static_cycles: u32,
|
||||
pub num_static_cycles: u64,
|
||||
pub num_spills_to_mem: u32,
|
||||
pub num_fills_from_mem: u32,
|
||||
pub num_spills_to_reg: u32,
|
||||
|
||||
@@ -240,8 +240,8 @@ pub fn side_effect_type(op: &Op) -> SideEffect {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn estimate_block_weight(cfg: &CFG<BasicBlock>, block_idx: usize) -> u32 {
|
||||
10_u32.pow(cfg.loop_depth(block_idx).try_into().unwrap())
|
||||
pub fn estimate_block_weight(cfg: &CFG<BasicBlock>, block_idx: usize) -> u64 {
|
||||
10_u64.pow(cfg.loop_depth(block_idx).try_into().unwrap())
|
||||
}
|
||||
|
||||
/// Try to guess how many cycles a variable latency instruction will take
|
||||
|
||||
@@ -141,14 +141,14 @@ fn generate_dep_graph(sm: &dyn ShaderModel, instrs: &[Box<Instr>]) -> DepGraph {
|
||||
fn generate_order(
|
||||
g: &mut DepGraph,
|
||||
init_ready_list: Vec<usize>,
|
||||
) -> (Vec<usize>, u32) {
|
||||
) -> (Vec<usize>, u64) {
|
||||
let mut ready_instrs: BinaryHeap<ReadyInstr> = BinaryHeap::new();
|
||||
let mut future_ready_instrs: BinaryHeap<FutureReadyInstr> = init_ready_list
|
||||
.into_iter()
|
||||
.map(|i| FutureReadyInstr::new(g, i))
|
||||
.collect();
|
||||
|
||||
let mut current_cycle = 0;
|
||||
let mut current_cycle = 0u32;
|
||||
let mut instr_order = Vec::with_capacity(g.nodes.len());
|
||||
loop {
|
||||
// Move ready instructions to the ready list
|
||||
@@ -198,13 +198,13 @@ fn generate_order(
|
||||
}
|
||||
}
|
||||
|
||||
(instr_order, current_cycle)
|
||||
(instr_order, u64::from(current_cycle))
|
||||
}
|
||||
|
||||
fn sched_buffer(
|
||||
sm: &dyn ShaderModel,
|
||||
instrs: Vec<Box<Instr>>,
|
||||
) -> (impl Iterator<Item = Box<Instr>> + use<>, u32) {
|
||||
) -> (impl Iterator<Item = Box<Instr>> + use<>, u64) {
|
||||
let mut g = generate_dep_graph(sm, &instrs);
|
||||
let init_ready_list = calc_statistics(&mut g);
|
||||
// save_graphviz(&instrs, &g).unwrap();
|
||||
@@ -221,8 +221,8 @@ fn sched_buffer(
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn opt_instr_sched_postpass(&mut self, sm: &dyn ShaderModel) -> u32 {
|
||||
let mut num_static_cycles = 0;
|
||||
pub fn opt_instr_sched_postpass(&mut self, sm: &dyn ShaderModel) -> u64 {
|
||||
let mut num_static_cycles = 0u64;
|
||||
for i in 0..self.blocks.len() {
|
||||
let block = &mut self.blocks[i];
|
||||
|
||||
@@ -232,8 +232,12 @@ impl Function {
|
||||
block.instrs = instrs.collect();
|
||||
assert_eq!(orig_instr_count, block.instrs.len());
|
||||
|
||||
num_static_cycles +=
|
||||
cycle_count * estimate_block_weight(&self.blocks, i);
|
||||
let block_weight = estimate_block_weight(&self.blocks, i);
|
||||
num_static_cycles = cycle_count
|
||||
.checked_mul(block_weight)
|
||||
.expect("Cycle count estimate overflow")
|
||||
.checked_add(num_static_cycles)
|
||||
.expect("Cycle count estimate overflow");
|
||||
}
|
||||
num_static_cycles
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user