Skip to content
Snippets Groups Projects
Commit 95a1e726 authored by Russel Arbore's avatar Russel Arbore
Browse files

Lift math on dynamic constants in IR to dynamic constant math

parent 925648e2
No related branches found
No related tags found
1 merge request!121Lift math on dynamic constants in IR to dynamic constant math
Pipeline #201143 passed
...@@ -8,7 +8,7 @@ use crate::*; ...@@ -8,7 +8,7 @@ use crate::*;
*/ */
pub fn dce(editor: &mut FunctionEditor) { pub fn dce(editor: &mut FunctionEditor) {
// Create worklist (starts as all nodes). // Create worklist (starts as all nodes).
let mut worklist: Vec<NodeID> = (0..editor.func().nodes.len()).map(NodeID::new).collect(); let mut worklist: Vec<NodeID> = editor.node_ids().collect();
while let Some(work) = worklist.pop() { while let Some(work) = worklist.pop() {
// If a node on the worklist is a start node, it is either *the* start // If a node on the worklist is a start node, it is either *the* start
......
...@@ -13,6 +13,7 @@ pub mod gcm; ...@@ -13,6 +13,7 @@ pub mod gcm;
pub mod gvn; pub mod gvn;
pub mod inline; pub mod inline;
pub mod interprocedural_sroa; pub mod interprocedural_sroa;
pub mod lift_dc_math;
pub mod outline; pub mod outline;
pub mod phi_elim; pub mod phi_elim;
pub mod pred; pub mod pred;
...@@ -35,6 +36,7 @@ pub use crate::gcm::*; ...@@ -35,6 +36,7 @@ pub use crate::gcm::*;
pub use crate::gvn::*; pub use crate::gvn::*;
pub use crate::inline::*; pub use crate::inline::*;
pub use crate::interprocedural_sroa::*; pub use crate::interprocedural_sroa::*;
pub use crate::lift_dc_math::*;
pub use crate::outline::*; pub use crate::outline::*;
pub use crate::phi_elim::*; pub use crate::phi_elim::*;
pub use crate::pred::*; pub use crate::pred::*;
......
use hercules_ir::ir::*;
use crate::*;
/*
* Lift math in IR nodes into dynamic constants.
*/
pub fn lift_dc_math(editor: &mut FunctionEditor) {
// Create worklist (starts as all nodes).
let mut worklist: Vec<NodeID> = editor.node_ids().collect();
while let Some(work) = worklist.pop() {
// Look for single nodes that can be converted to dynamic constants.
let users: Vec<_> = editor.get_users(work).collect();
let nodes = &editor.func().nodes;
let dc = match nodes[work.idx()] {
Node::Constant { id } => {
// Why do we need this weird crap? This is due to a limitation
// in Rust's lifetime rules w/ let guards.
let cons = if let Constant::UnsignedInteger64(cons) = *editor.get_constant(id) {
cons
} else {
continue;
};
DynamicConstant::Constant(cons as usize)
}
Node::DynamicConstant { id } => {
let Some(cons) = evaluate_dynamic_constant(id, &*editor.get_dynamic_constants())
else {
continue;
};
DynamicConstant::Constant(cons)
}
Node::Binary { op, left, right } => {
let (left, right) = if let (
Node::DynamicConstant { id: left },
Node::DynamicConstant { id: right },
) = (&nodes[left.idx()], &nodes[right.idx()])
{
(*left, *right)
} else {
continue;
};
match op {
BinaryOperator::Add => DynamicConstant::Add(left, right),
BinaryOperator::Sub => DynamicConstant::Sub(left, right),
BinaryOperator::Mul => DynamicConstant::Mul(left, right),
BinaryOperator::Div => DynamicConstant::Div(left, right),
BinaryOperator::Rem => DynamicConstant::Rem(left, right),
_ => {
continue;
}
}
}
Node::IntrinsicCall {
intrinsic,
ref args,
} => {
let (left, right) = if args.len() == 2
&& let (Node::DynamicConstant { id: left }, Node::DynamicConstant { id: right }) =
(&nodes[args[0].idx()], &nodes[args[1].idx()])
{
(*left, *right)
} else {
continue;
};
match intrinsic {
Intrinsic::Min => DynamicConstant::Min(left, right),
Intrinsic::Max => DynamicConstant::Max(left, right),
_ => {
continue;
}
}
}
_ => {
continue;
}
};
// Replace the node with the computed dynamic constant.
let success = editor.edit(|mut edit| {
let dc = edit.add_dynamic_constant(dc);
let node = edit.add_node(Node::DynamicConstant { id: dc });
edit = edit.replace_all_uses(work, node)?;
edit.delete_node(work)
});
if success {
worklist.extend(users);
}
}
}
...@@ -60,6 +60,10 @@ pub fn default_schedule() -> ScheduleStmt { ...@@ -60,6 +60,10 @@ pub fn default_schedule() -> ScheduleStmt {
DCE, DCE,
GVN, GVN,
DCE, DCE,
LiftDCMath,
DCE,
GVN,
DCE,
/*Forkify,*/ /*Forkify,*/
/*ForkGuardElim,*/ /*ForkGuardElim,*/
DCE, DCE,
......
...@@ -18,6 +18,7 @@ pub enum Pass { ...@@ -18,6 +18,7 @@ pub enum Pass {
InferSchedules, InferSchedules,
Inline, Inline,
InterproceduralSROA, InterproceduralSROA,
LiftDCMath,
Outline, Outline,
PhiElim, PhiElim,
Predication, Predication,
......
...@@ -6,8 +6,8 @@ use hercules_opt::FunctionEditor; ...@@ -6,8 +6,8 @@ use hercules_opt::FunctionEditor;
use hercules_opt::{ use hercules_opt::{
ccp, collapse_returns, crc, dce, dumb_outline, ensure_between_control_flow, float_collections, ccp, collapse_returns, crc, dce, dumb_outline, ensure_between_control_flow, float_collections,
fork_split, gcm, gvn, infer_parallel_fork, infer_parallel_reduce, infer_tight_associative, fork_split, gcm, gvn, infer_parallel_fork, infer_parallel_reduce, infer_tight_associative,
infer_vectorizable, inline, interprocedural_sroa, outline, phi_elim, predication, slf, sroa, infer_vectorizable, inline, interprocedural_sroa, lift_dc_math, outline, phi_elim, predication,
unforkify, write_predication, slf, sroa, unforkify, write_predication,
}; };
use tempfile::TempDir; use tempfile::TempDir;
...@@ -1339,6 +1339,18 @@ fn run_pass( ...@@ -1339,6 +1339,18 @@ fn run_pass(
pm.delete_gravestones(); pm.delete_gravestones();
pm.clear_analyses(); pm.clear_analyses();
} }
Pass::LiftDCMath => {
assert!(args.is_empty());
for func in build_selection(pm, selection) {
let Some(mut func) = func else {
continue;
};
lift_dc_math(&mut func);
changed |= func.modified();
}
pm.delete_gravestones();
pm.clear_analyses();
}
Pass::Outline => { Pass::Outline => {
let Some((nodes, func)) = selection_as_set(pm, selection) else { let Some((nodes, func)) = selection_as_set(pm, selection) else {
return Err(SchedulerError::PassError { return Err(SchedulerError::PassError {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment