Skip to content
Snippets Groups Projects
Commit eed60d07 authored by rarbore2's avatar rarbore2
Browse files

Merge branch 'lift_to_dc_math' into 'main'

Lift math on dynamic constants in IR to dynamic constant math

See merge request !121
parents 925648e2 95a1e726
No related branches found
No related tags found
1 merge request!121Lift math on dynamic constants in IR to dynamic constant math
Pipeline #201144 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