duskphantom_middle/transform/
loop_optimization.rs

1// Copyright 2024 Duskphantom Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17use std::collections::{HashMap, VecDeque};
18
19use super::*;
20use crate::{
21    analysis::{
22        effect_analysis::EffectAnalysis,
23        loop_tools::{self, LoopForest, LoopPtr},
24        memory_ssa::MemorySSA,
25    },
26    ir::FunPtr,
27    Program,
28};
29use anyhow::{Ok, Result};
30
31pub fn optimize_program(program: &mut Program) -> Result<()> {
32    let effect_analysis = EffectAnalysis::new(program);
33    let mut memory_ssa = MemorySSA::new(program, &effect_analysis);
34    let mut func_loop_map = program
35        .module
36        .functions
37        .iter_mut()
38        .filter_map(|func| loop_tools::LoopForest::make_forest(*func).map(|forest| (*func, forest)))
39        .collect::<HashMap<FunPtr, LoopForest>>();
40
41    for (_, forest) in func_loop_map.iter_mut() {
42        loop_simplify::LoopSimplifier::new(&mut program.mem_pool).run(forest)?;
43        licm::LICM::new(&mut program.mem_pool, &mut memory_ssa).run(forest)?;
44        ldce::LDCE::new(&mut program.mem_pool, &effect_analysis).run(forest)?;
45        loop_depth::LoopDepthTracer::run(forest)?;
46    }
47
48    Ok(())
49}
50
51pub fn loop_forest_post_order<F>(loop_forest: &mut LoopForest, mut f: F) -> Result<()>
52where
53    F: FnMut(LoopPtr) -> Result<()>,
54{
55    let mut stack = Vec::new();
56    let mut queue = VecDeque::from(loop_forest.forest.clone());
57    while let Some(lo) = queue.pop_front() {
58        queue.extend(lo.sub_loops.iter());
59        stack.push(lo);
60    }
61
62    while let Some(lo) = stack.pop() {
63        f(lo)?;
64    }
65
66    Ok(())
67}