cubecl_opt/analyses/
base.rs

1use std::{any::Any, cell::RefCell, rc::Rc};
2
3use type_map::TypeMap;
4
5use crate::Optimizer;
6
7use super::{
8    dominance::{Dominators, PostDominators},
9    liveness::Liveness,
10    post_order::PostOrder,
11};
12
13/// An analysis used by optimization passes. Unlike optimization passes, analyses can have state
14/// and persist until they're invalidated.
15pub trait Analysis {
16    /// Perform the analysis for the current optimizer state and return the persistent analysis state
17    fn init(opt: &mut Optimizer) -> Self;
18}
19
20#[derive(Default, Clone, Debug)]
21pub struct AnalysisCache {
22    cache: Rc<RefCell<TypeMap>>,
23}
24
25impl AnalysisCache {
26    pub fn get<A: Analysis + Any>(&self, opt: &mut Optimizer) -> Rc<A> {
27        let analysis = self.cache.borrow().get::<Rc<A>>().cloned();
28        if let Some(analysis) = analysis {
29            analysis
30        } else {
31            let analysis = Rc::new(A::init(opt));
32            self.cache.borrow_mut().insert(analysis.clone());
33            analysis
34        }
35    }
36
37    pub fn try_get<A: Any>(&self) -> Option<Rc<A>> {
38        self.cache.borrow().get().cloned()
39    }
40
41    pub fn invalidate<A: Analysis + Any>(&self) {
42        self.cache.borrow_mut().remove::<Rc<A>>();
43    }
44}
45
46impl Optimizer {
47    /// Fetch an analysis if cached, or run it if not.
48    pub fn analysis<A: Analysis + Any>(&mut self) -> Rc<A> {
49        let analyses = self.analysis_cache.clone();
50        analyses.get(self)
51    }
52
53    /// Invalidate an analysis by removing it from the cache. The analysis is rerun when requested
54    /// again.
55    pub fn invalidate_analysis<A: Analysis + Any>(&self) {
56        self.analysis_cache.invalidate::<A>();
57    }
58
59    /// Invalidate all analyses that rely on the structure of the control flow graph.
60    pub fn invalidate_structure(&self) {
61        self.invalidate_analysis::<PostOrder>();
62        self.invalidate_analysis::<Dominators>();
63        self.invalidate_analysis::<PostDominators>();
64        self.invalidate_analysis::<Liveness>();
65    }
66}