Only record vreg definitions when fuzzing (#66)

The `vreg_def_blockparam` and `vreg_def_inst` fields on CFGInfo are only
used in `validate_ssa`, which in turn is only used in the ssagen fuzz
target.

Since these fields are never read in normal usage, initializing them is
entirely wasted effort. According to valgrind/DHAT, when running
`wasmtime compile` on the Sightglass Spidermonkey benchmark, removing
these fields saves about 100M instructions, 23k heap allocations
totalling 40MiB, and 47MiB of writes to the heap.
This commit is contained in:
Jamey Sharp
2022-07-29 10:25:27 -07:00
committed by GitHub
parent 0eb3deb384
commit 1955c6dfb5
4 changed files with 29 additions and 29 deletions

View File

@@ -5,7 +5,7 @@
//! Lightweight CFG analyses.
use crate::{domtree, postorder, Block, Function, Inst, OperandKind, ProgPoint, RegAllocError};
use crate::{domtree, postorder, Block, Function, Inst, ProgPoint, RegAllocError};
use smallvec::{smallvec, SmallVec};
#[derive(Clone, Debug)]
@@ -16,12 +16,6 @@ pub struct CFGInfo {
pub domtree: Vec<Block>,
/// For each instruction, the block it belongs to.
pub insn_block: Vec<Block>,
/// For each vreg, the instruction that defines it, if any.
pub vreg_def_inst: Vec<Inst>,
/// For each vreg, the block that defines it as a blockparam, if
/// any. (Every vreg must have a valid entry in either
/// `vreg_def_inst` or `vreg_def_blockparam`.)
pub vreg_def_blockparam: Vec<(Block, u32)>,
/// For each block, the first instruction.
pub block_entry: Vec<ProgPoint>,
/// For each block, the last instruction.
@@ -48,8 +42,6 @@ impl CFGInfo {
f.entry_block(),
);
let mut insn_block = vec![Block::invalid(); f.num_insts()];
let mut vreg_def_inst = vec![Inst::invalid(); f.num_vregs()];
let mut vreg_def_blockparam = vec![(Block::invalid(), 0); f.num_vregs()];
let mut block_entry = vec![ProgPoint::before(Inst::invalid()); f.num_blocks()];
let mut block_exit = vec![ProgPoint::before(Inst::invalid()); f.num_blocks()];
let mut backedge_in = vec![0; f.num_blocks()];
@@ -57,19 +49,8 @@ impl CFGInfo {
for block in 0..f.num_blocks() {
let block = Block::new(block);
for (i, param) in f.block_params(block).iter().enumerate() {
vreg_def_blockparam[param.vreg()] = (block, i as u32);
}
for inst in f.block_insns(block).iter() {
insn_block[inst.index()] = block;
for operand in f.inst_operands(inst) {
match operand.kind() {
OperandKind::Def => {
vreg_def_inst[operand.vreg().vreg()] = inst;
}
_ => {}
}
}
}
block_entry[block.index()] = ProgPoint::before(f.block_insns(block).first());
block_exit[block.index()] = ProgPoint::after(f.block_insns(block).last());
@@ -139,8 +120,6 @@ impl CFGInfo {
postorder,
domtree,
insn_block,
vreg_def_inst,
vreg_def_blockparam,
block_entry,
block_exit,
approx_loop_depth,

View File

@@ -6,6 +6,7 @@
//! Utilities for fuzzing.
pub mod func;
pub mod ssa;
// Re-exports for fuzz targets.
@@ -21,9 +22,6 @@ pub mod moves {
pub mod cfg {
pub use crate::cfg::*;
}
pub mod ssa {
pub use crate::ssa::*;
}
pub mod ion {
pub use crate::ion::*;
}

View File

@@ -10,6 +10,30 @@ use crate::cfg::CFGInfo;
use crate::{Block, Function, Inst, OperandKind, RegAllocError};
pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllocError> {
// For each vreg, the instruction that defines it, if any.
let mut vreg_def_inst = vec![Inst::invalid(); f.num_vregs()];
// For each vreg, the block that defines it as a blockparam, if
// any. (Every vreg must have a valid entry in either
// `vreg_def_inst` or `vreg_def_blockparam`.)
let mut vreg_def_blockparam = vec![(Block::invalid(), 0); f.num_vregs()];
for block in 0..f.num_blocks() {
let block = Block::new(block);
for (i, param) in f.block_params(block).iter().enumerate() {
vreg_def_blockparam[param.vreg()] = (block, i as u32);
}
for inst in f.block_insns(block).iter() {
for operand in f.inst_operands(inst) {
match operand.kind() {
OperandKind::Def => {
vreg_def_inst[operand.vreg().vreg()] = inst;
}
_ => {}
}
}
}
}
// Walk the blocks in arbitrary order. Check, for every use, that
// the def is either in the same block in an earlier inst, or is
// defined (by inst or blockparam) in some other block that
@@ -29,10 +53,10 @@ pub fn validate_ssa<F: Function>(f: &F, cfginfo: &CFGInfo) -> Result<(), RegAllo
for operand in operands {
match operand.kind() {
OperandKind::Use => {
let def_block = if cfginfo.vreg_def_inst[operand.vreg().vreg()].is_valid() {
cfginfo.insn_block[cfginfo.vreg_def_inst[operand.vreg().vreg()].index()]
let def_block = if vreg_def_inst[operand.vreg().vreg()].is_valid() {
cfginfo.insn_block[vreg_def_inst[operand.vreg().vreg()].index()]
} else {
cfginfo.vreg_def_blockparam[operand.vreg().vreg()].0
vreg_def_blockparam[operand.vreg().vreg()].0
};
if def_block.is_invalid() {
return Err(RegAllocError::SSA(operand.vreg(), iix));

View File

@@ -34,7 +34,6 @@ pub mod indexset;
pub(crate) mod ion;
pub(crate) mod moves;
pub(crate) mod postorder;
pub(crate) mod ssa;
#[macro_use]
mod index;