Coverage Report

Created: 2023-04-25 07:07

/rust/registry/src/index.crates.io-6f17d22bba15001f/egg-0.6.0/src/egraph.rs
Line
Count
Source (jump to first uncovered line)
1
use std::collections::HashMap;
2
use std::{
3
    borrow::BorrowMut,
4
    fmt::{self, Debug},
5
};
6
7
use indexmap::IndexMap;
8
use log::*;
9
10
use crate::{
11
    Analysis, AstSize, Dot, EClass, Extractor, Id, Language, Pattern, RecExpr, Searcher, UnionFind,
12
};
13
14
/** A data structure to keep track of equalities between expressions.
15
16
# What's an egraph?
17
18
An egraph ([/'igraf/][sound]) is a data structure to maintain equivalence
19
20
classes of expressions.
21
An egraph conceptually is a set of eclasses, each of which
22
contains equivalent enodes.
23
An enode is conceptually and operator with children, but instead of
24
children being other operators or values, the children are eclasses.
25
26
In `egg`, these are respresented by the [`EGraph`], [`EClass`], and
27
[`Language`] (enodes) types.
28
29
30
Here's an egraph created and rendered by [this example](struct.Dot.html).
31
As described in the documentation for [egraph visualization][dot] and
32
in the academic literature, we picture eclasses as dotted boxes
33
surrounding the equivalent enodes:
34
35
<img src="https://mwillsey.com/assets/simple-egraph.svg"/>
36
37
We say a term _t_ is _represented_ in an eclass _e_ if you can pick a
38
single enode from each eclass such that _t_ is in _e_.
39
A term is represented in the egraph if it's represented in any eclass.
40
In the image above, the terms `2 * a`, `a * 2`, and `a << 1` are all
41
represented in the same eclass and thus are equivalent.
42
The terms `1`, `(a * 2) / 2`, and `(a << 1) / 2` are represented in
43
the egraph, but not in the same eclass as the prior three terms, so
44
these three are not equivalent to those three.
45
46
Egraphs are useful when you have a bunch of very similar expressions,
47
some of which are equivalent, and you'd like a compactly store them.
48
This compactness allows rewrite systems based on egraphs to
49
efficiently "remember" the expression before and after rewriting, so
50
you can essentially apply all rewrites at once.
51
See [`Rewrite`] and [`Runner`] for more details about rewrites and
52
running rewrite systems, respectively.
53
54
# Invariants and Rebuilding
55
56
An egraph has two core operations that modify the egraph:
57
[`add`] which adds enodes to the egraph, and
58
[`union`] which merges two eclasses.
59
These operations maintains two key (related) invariants:
60
61
1. **Uniqueness of enodes**
62
63
   There do not exist two distinct enodes with equal operators and equal
64
   children in the eclass, either in the same eclass or different eclasses.
65
   This is maintained in part by the hashconsing performed by [`add`],
66
   and by deduplication performed by [`union`] and [`rebuild`].
67
68
2. **Congruence closure**
69
70
   An egraph maintains not just an [equivalence relation] over
71
   expressions, but a [congruence relation].
72
   So as the user calls [`union`], many eclasses other than the given
73
   two may need to merge to maintain congruence.
74
75
   For example, suppose terms `a + x` and `a + y` are represented in
76
   eclasses 1 and 2, respectively.
77
   At some later point, `x` and `y` become
78
   equivalent (perhaps the user called [`union`] on their containing
79
   eclasses).
80
   Eclasses 1 and 2 must merge, because now the two `+`
81
   operators have equivalent arguments, making them equivalent.
82
83
`egg` takes a delayed approach to maintaining these invariants.
84
Specifically, the effects of calling [`union`] (or applying a rewrite,
85
which calls [`union`]) may not be reflected immediately.
86
To restore the egraph invariants and make these effects visible, the
87
user *must* call the [`rebuild`] method.
88
89
`egg`s choice here allows for a higher performance implementation.
90
Maintaining the congruence relation complicates the core egraph data
91
structure and requires an expensive traversal through the egraph on
92
every [`union`].
93
`egg` chooses to relax these invariants for better performance, only
94
restoring the invariants on a call to [`rebuild`].
95
See the [`rebuild`] documentation for more information.
96
Note also that [`Runner`]s take care of this for you, calling
97
[`rebuild`] between rewrite iterations.
98
99
# egraphs in `egg`
100
101
In `egg`, the main types associated with egraphs are
102
[`EGraph`], [`EClass`], [`Language`], and [`Id`].
103
104
[`EGraph`] and [`EClass`] are all generic over a
105
[`Language`], meaning that types actually floating around in the
106
egraph are all user-defined.
107
In particular, the enodes are elements of your [`Language`].
108
[`EGraph`]s and [`EClass`]es are additionally parameterized by some
109
[`Analysis`], abritrary data associated with each eclass.
110
111
Many methods of [`EGraph`] deal with [`Id`]s, which represent eclasses.
112
Because eclasses are frequently merged, many [`Id`]s will refer to the
113
same eclass.
114
115
[`EGraph`]: struct.EGraph.html
116
[`EClass`]: struct.EClass.html
117
[`Rewrite`]: struct.Rewrite.html
118
[`Runner`]: struct.Runner.html
119
[`Language`]: trait.Language.html
120
[`Analysis`]: trait.Analysis.html
121
[`Id`]: struct.Id.html
122
[`add`]: struct.EGraph.html#method.add
123
[`union`]: struct.EGraph.html#method.union
124
[`rebuild`]: struct.EGraph.html#method.rebuild
125
[equivalence relation]: https://en.wikipedia.org/wiki/Equivalence_relation
126
[congruence relation]: https://en.wikipedia.org/wiki/Congruence_relation
127
[dot]: struct.Dot.html
128
[extract]: struct.Extractor.html
129
[sound]: https://itinerarium.github.io/phoneme-synthesis/?w=/'igraf/
130
**/
131
2.68k
#[derive(Clone)]
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::clone::Clone>::clone
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::clone::Clone>::clone
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::clone::Clone>::clone
Line
Count
Source
131
2.68k
#[derive(Clone)]
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::clone::Clone>::clone
132
pub struct EGraph<L: Language, N: Analysis<L>> {
133
    /// The `Analysis` given when creating this `EGraph`.
134
    pub analysis: N,
135
    memo: HashMap<L, Id>,
136
    unionfind: UnionFind,
137
    classes: SparseVec<EClass<L, N::Data>>,
138
    dirty_unions: Vec<Id>,
139
    repairs_since_rebuild: usize,
140
    pub(crate) classes_by_op: IndexMap<std::mem::Discriminant<L>, indexmap::IndexSet<Id>>,
141
}
142
143
type SparseVec<T> = Vec<Option<Box<T>>>;
144
145
impl<L: Language, N: Analysis<L> + Default> Default for EGraph<L, N> {
146
0
    fn default() -> Self {
147
0
        Self::new(N::default())
148
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::default::Default>::default
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::default::Default>::default
149
}
150
151
// manual debug impl to avoid L: Language bound on EGraph defn
152
impl<L: Language, N: Analysis<L>> Debug for EGraph<L, N> {
153
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
154
0
        f.debug_struct("EGraph")
155
0
            .field("memo", &self.memo)
156
0
            .field("classes", &self.classes)
157
0
            .finish()
158
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::fmt::Debug>::fmt
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::fmt::Debug>::fmt
159
}
160
161
impl<L: Language, N: Analysis<L>> EGraph<L, N> {
162
    /// Creates a new, empty `EGraph` with the given `Analysis`
163
2.68k
    pub fn new(analysis: N) -> Self {
164
2.68k
        Self {
165
2.68k
            analysis,
166
2.68k
            memo: Default::default(),
167
2.68k
            classes: Default::default(),
168
2.68k
            unionfind: Default::default(),
169
2.68k
            dirty_unions: Default::default(),
170
2.68k
            classes_by_op: IndexMap::default(),
171
2.68k
            repairs_since_rebuild: 0,
172
2.68k
        }
173
2.68k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::new
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::new
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::new
Line
Count
Source
163
2.68k
    pub fn new(analysis: N) -> Self {
164
2.68k
        Self {
165
2.68k
            analysis,
166
2.68k
            memo: Default::default(),
167
2.68k
            classes: Default::default(),
168
2.68k
            unionfind: Default::default(),
169
2.68k
            dirty_unions: Default::default(),
170
2.68k
            classes_by_op: IndexMap::default(),
171
2.68k
            repairs_since_rebuild: 0,
172
2.68k
        }
173
2.68k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::new
174
175
    /// Returns an iterator over the eclasses in the egraph.
176
282k
    pub fn classes(&self) -> impl Iterator<Item = &EClass<L, N::Data>> {
177
282k
        self.classes
178
282k
            .iter()
179
282k
            .filter_map(Option::as_ref)
180
282k
            .map(AsRef::as_ref)
181
282k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::classes
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::classes
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::classes
Line
Count
Source
176
282k
    pub fn classes(&self) -> impl Iterator<Item = &EClass<L, N::Data>> {
177
282k
        self.classes
178
282k
            .iter()
179
282k
            .filter_map(Option::as_ref)
180
282k
            .map(AsRef::as_ref)
181
282k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::classes
182
183
    /// Returns an mutating iterator over the eclasses in the egraph.
184
0
    pub fn classes_mut(&mut self) -> impl Iterator<Item = &mut EClass<L, N::Data>> {
185
0
        self.classes
186
0
            .iter_mut()
187
0
            .filter_map(Option::as_mut)
188
0
            .map(AsMut::as_mut)
189
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::classes_mut
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::classes_mut
190
191
    /// Returns `true` if the egraph is empty
192
    /// # Example
193
    /// ```
194
    /// use egg::{*, SymbolLang as S};
195
    /// let mut egraph = EGraph::<S, ()>::default();
196
    /// assert!(egraph.is_empty());
197
    /// egraph.add(S::leaf("foo"));
198
    /// assert!(!egraph.is_empty());
199
    /// ```
200
0
    pub fn is_empty(&self) -> bool {
201
0
        self.memo.is_empty()
202
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::is_empty
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::is_empty
203
204
    /// Returns the number of enodes in the `EGraph`.
205
    ///
206
    /// Actually returns the size of the hashcons index.
207
    /// # Example
208
    /// ```
209
    /// use egg::{*, SymbolLang as S};
210
    /// let mut egraph = EGraph::<S, ()>::default();
211
    /// let x = egraph.add(S::leaf("x"));
212
    /// let y = egraph.add(S::leaf("y"));
213
    /// // only one eclass
214
    /// egraph.union(x, y);
215
    /// egraph.rebuild();
216
    ///
217
    /// assert_eq!(egraph.total_size(), 2);
218
    /// assert_eq!(egraph.number_of_classes(), 1);
219
    /// ```
220
710k
    pub fn total_size(&self) -> usize {
221
710k
        self.memo.len()
222
710k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_size
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_size
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_size
Line
Count
Source
220
710k
    pub fn total_size(&self) -> usize {
221
710k
        self.memo.len()
222
710k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_size
223
224
    /// Iterates over the classes, returning the total number of nodes.
225
5.37k
    pub fn total_number_of_nodes(&self) -> usize {
226
34.0k
        self.classes().map(|c| c.len()).sum()
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_number_of_nodes::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_number_of_nodes::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_number_of_nodes::{closure#0}
Line
Count
Source
226
34.0k
        self.classes().map(|c| c.len()).sum()
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_number_of_nodes::{closure#0}
227
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_number_of_nodes
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_number_of_nodes
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::total_number_of_nodes
Line
Count
Source
225
5.37k
    pub fn total_number_of_nodes(&self) -> usize {
226
5.37k
        self.classes().map(|c| c.len()).sum()
227
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::total_number_of_nodes
228
229
    /// Returns the number of eclasses in the egraph.
230
10.7k
    pub fn number_of_classes(&self) -> usize {
231
10.7k
        self.classes().count()
232
10.7k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::number_of_classes
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::number_of_classes
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::number_of_classes
Line
Count
Source
230
10.7k
    pub fn number_of_classes(&self) -> usize {
231
10.7k
        self.classes().count()
232
10.7k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::number_of_classes
233
234
    /// Canonicalizes an eclass id.
235
    ///
236
    /// This corresponds to the `find` operation on the egraph's
237
    /// underlying unionfind data structure.
238
    ///
239
    /// # Example
240
    /// ```
241
    /// use egg::{*, SymbolLang as S};
242
    /// let mut egraph = EGraph::<S, ()>::default();
243
    /// let x = egraph.add(S::leaf("x"));
244
    /// let y = egraph.add(S::leaf("y"));
245
    /// assert_ne!(egraph.find(x), egraph.find(y));
246
    ///
247
    /// egraph.union(x, y);
248
    /// assert_eq!(egraph.find(x), egraph.find(y));
249
    /// ```
250
15.7M
    pub fn find(&self, id: Id) -> Id {
251
15.7M
        self.unionfind.find(id)
252
15.7M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::find
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::find
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::find
Line
Count
Source
250
15.7M
    pub fn find(&self, id: Id) -> Id {
251
15.7M
        self.unionfind.find(id)
252
15.7M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::find
253
254
    /// Creates a [`Dot`] to visualize this egraph. See [`Dot`].
255
    ///
256
    /// [`Dot`]: struct.Dot.html
257
0
    pub fn dot(&self) -> Dot<L, N> {
258
0
        Dot { egraph: self }
259
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::dot
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::dot
260
}
261
262
impl<L: Language, N: Analysis<L>> std::ops::Index<Id> for EGraph<L, N> {
263
    type Output = EClass<L, N::Data>;
264
2.68M
    fn index(&self, id: Id) -> &Self::Output {
265
2.68M
        let id = self.find(id);
266
2.68M
        self.classes[usize::from(id)]
267
2.68M
            .as_ref()
268
2.68M
            .unwrap_or_else(|| panic!("Invalid id {}", id))
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::Index<egg::Id>>::index::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::Index<egg::Id>>::index::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::Index<egg::Id>>::index::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::Index<egg::Id>>::index::{closure#0}
269
2.68M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::Index<egg::Id>>::index
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::Index<egg::Id>>::index
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::Index<egg::Id>>::index
Line
Count
Source
264
2.68M
    fn index(&self, id: Id) -> &Self::Output {
265
2.68M
        let id = self.find(id);
266
2.68M
        self.classes[usize::from(id)]
267
2.68M
            .as_ref()
268
2.68M
            .unwrap_or_else(|| panic!("Invalid id {}", id))
269
2.68M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::Index<egg::Id>>::index
270
}
271
272
impl<L: Language, N: Analysis<L>> std::ops::IndexMut<Id> for EGraph<L, N> {
273
1.05M
    fn index_mut(&mut self, id: Id) -> &mut Self::Output {
274
1.05M
        let id = self.find(id);
275
1.05M
        self.classes[usize::from(id)]
276
1.05M
            .as_mut()
277
1.05M
            .unwrap_or_else(|| panic!("Invalid id {}", id))
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::IndexMut<egg::Id>>::index_mut::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::IndexMut<egg::Id>>::index_mut::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::IndexMut<egg::Id>>::index_mut::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::IndexMut<egg::Id>>::index_mut::{closure#0}
278
1.05M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::IndexMut<egg::Id>>::index_mut
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::IndexMut<egg::Id>>::index_mut
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::ops::index::IndexMut<egg::Id>>::index_mut
Line
Count
Source
273
1.05M
    fn index_mut(&mut self, id: Id) -> &mut Self::Output {
274
1.05M
        let id = self.find(id);
275
1.05M
        self.classes[usize::from(id)]
276
1.05M
            .as_mut()
277
1.05M
            .unwrap_or_else(|| panic!("Invalid id {}", id))
278
1.05M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _> as core::ops::index::IndexMut<egg::Id>>::index_mut
279
}
280
281
impl<L: Language, N: Analysis<L>> EGraph<L, N> {
282
    /// Adds a [`RecExpr`] to the [`EGraph`].
283
    ///
284
    /// # Example
285
    /// ```
286
    /// use egg::{*, SymbolLang as S};
287
    /// let mut egraph = EGraph::<S, ()>::default();
288
    /// let x = egraph.add(S::leaf("x"));
289
    /// let y = egraph.add(S::leaf("y"));
290
    /// let plus = egraph.add(S::new("+", vec![x, y]));
291
    /// let plus_recexpr = "(+ x y)".parse().unwrap();
292
    /// assert_eq!(plus, egraph.add_expr(&plus_recexpr));
293
    /// ```
294
    ///
295
    /// [`EGraph`]: struct.EGraph.html
296
    /// [`RecExpr`]: struct.RecExpr.html
297
    /// [`add_expr`]: struct.EGraph.html#method.add_expr
298
5.37k
    pub fn add_expr(&mut self, expr: &RecExpr<L>) -> Id {
299
5.37k
        self.add_expr_rec(expr.as_ref())
300
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr
Line
Count
Source
298
5.37k
    pub fn add_expr(&mut self, expr: &RecExpr<L>) -> Id {
299
5.37k
        self.add_expr_rec(expr.as_ref())
300
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr
301
302
92.9k
    fn add_expr_rec(&mut self, expr: &[L]) -> Id {
303
92.9k
        log::trace!("Adding expr {:?}", expr);
304
92.9k
        let e = expr.last().unwrap().clone().map_children(|i| {
305
87.6k
            let child = &expr[..usize::from(i) + 1];
306
87.6k
            self.add_expr_rec(child)
307
92.9k
        });
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr_rec::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr_rec::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr_rec::{closure#0}
Line
Count
Source
304
87.6k
        let e = expr.last().unwrap().clone().map_children(|i| {
305
87.6k
            let child = &expr[..usize::from(i) + 1];
306
87.6k
            self.add_expr_rec(child)
307
87.6k
        });
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr_rec::{closure#0}
308
92.9k
        let id = self.add(e);
309
92.9k
        log::trace!("Added!! expr {:?}", expr);
310
92.9k
        id
311
92.9k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr_rec
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr_rec
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add_expr_rec
Line
Count
Source
302
92.9k
    fn add_expr_rec(&mut self, expr: &[L]) -> Id {
303
92.9k
        log::trace!("Adding expr {:?}", expr);
304
92.9k
        let e = expr.last().unwrap().clone().map_children(|i| {
305
            let child = &expr[..usize::from(i) + 1];
306
            self.add_expr_rec(child)
307
92.9k
        });
308
92.9k
        let id = self.add(e);
309
92.9k
        log::trace!("Added!! expr {:?}", expr);
310
92.9k
        id
311
92.9k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add_expr_rec
312
313
    /// Lookup the eclass of the given enode.
314
    ///
315
    /// You can pass in either an owned enode or a `&mut` enode,
316
    /// in which case the enode's children will be canonicalized.
317
    ///
318
    /// # Example
319
    /// ```
320
    /// # use egg::*;
321
    /// let mut egraph: EGraph<SymbolLang, ()> = Default::default();
322
    /// let a = egraph.add(SymbolLang::leaf("a"));
323
    /// let b = egraph.add(SymbolLang::leaf("b"));
324
    /// let c = egraph.add(SymbolLang::leaf("c"));
325
    ///
326
    /// // lookup will find this node if its in the egraph
327
    /// let mut node_f_ac = SymbolLang::new("f", vec![a, c]);
328
    /// assert_eq!(egraph.lookup(node_f_ac.clone()), None);
329
    /// let id = egraph.add(node_f_ac.clone());
330
    /// assert_eq!(egraph.lookup(node_f_ac.clone()), Some(id));
331
    ///
332
    /// // if the query node isn't canonical, and its passed in by &mut instead of owned,
333
    /// // its children will be canonicalized
334
    /// egraph.union(b, c);
335
    /// egraph.rebuild();
336
    /// assert_eq!(egraph.lookup(&mut node_f_ac), Some(id));
337
    /// assert_eq!(node_f_ac, SymbolLang::new("f", vec![a, b]));
338
    /// ```
339
1.62M
    pub fn lookup<B>(&self, mut enode: B) -> Option<Id>
340
1.62M
    where
341
1.62M
        B: BorrowMut<L>,
342
1.62M
    {
343
1.62M
        let enode = enode.borrow_mut();
344
1.62M
        enode.update_children(|id| self.find(id));
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>::{closure#0}
Line
Count
Source
344
1.56M
        enode.update_children(|id| self.find(id));
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>::{closure#0}
345
1.62M
        let id = self.memo.get(enode);
346
1.62M
        id.map(|&id| self.find(id))
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>::{closure#1}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>::{closure#1}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>::{closure#1}
Line
Count
Source
346
1.04M
        id.map(|&id| self.find(id))
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>::{closure#1}
347
1.62M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::lookup::<&mut wasm_mutate::mutators::peephole::eggsy::lang::Lang>
Line
Count
Source
339
1.62M
    pub fn lookup<B>(&self, mut enode: B) -> Option<Id>
340
1.62M
    where
341
1.62M
        B: BorrowMut<L>,
342
1.62M
    {
343
1.62M
        let enode = enode.borrow_mut();
344
1.62M
        enode.update_children(|id| self.find(id));
345
1.62M
        let id = self.memo.get(enode);
346
1.62M
        id.map(|&id| self.find(id))
347
1.62M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::lookup::<_>
348
349
    /// Adds an enode to the [`EGraph`].
350
    ///
351
    /// When adding an enode, to the egraph, [`add`] it performs
352
    /// _hashconsing_ (sometimes called interning in other contexts).
353
    ///
354
    /// Hashconsing ensures that only one copy of that enode is in the egraph.
355
    /// If a copy is in the egraph, then [`add`] simply returns the id of the
356
    /// eclass in which the enode was found.
357
    /// Otherwise
358
    ///
359
    /// [`EGraph`]: struct.EGraph.html
360
    /// [`EClass`]: struct.EClass.html
361
    /// [`add`]: struct.EGraph.html#method.add
362
1.62M
    pub fn add(&mut self, mut enode: L) -> Id {
363
1.62M
        self.lookup(&mut enode).unwrap_or_else(|| {
364
578k
            let id = self.unionfind.make_set();
365
578k
            log::trace!("  ...adding to {}", id);
366
578k
            let class = Box::new(EClass {
367
578k
                id,
368
578k
                nodes: vec![enode.clone()],
369
578k
                data: N::make(self, &enode),
370
578k
                parents: Default::default(),
371
578k
            });
372
578k
373
578k
            // add this enode to the parent lists of its children
374
1.04M
            enode.for_each(|child| {
375
1.04M
                let tup = (enode.clone(), id);
376
1.04M
                self[child].parents.push(tup);
377
1.04M
            });
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add::{closure#0}::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add::{closure#0}::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add::{closure#0}::{closure#0}
Line
Count
Source
374
1.04M
            enode.for_each(|child| {
375
1.04M
                let tup = (enode.clone(), id);
376
1.04M
                self[child].parents.push(tup);
377
1.04M
            });
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add::{closure#0}::{closure#0}
378
578k
379
578k
            assert_eq!(self.classes.len(), usize::from(id));
380
578k
            self.classes.push(Some(class));
381
578k
            assert!(self.memo.insert(enode, id).is_none());
382
383
578k
            N::modify(self, id);
384
578k
            id
385
1.62M
        })
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add::{closure#0}
Line
Count
Source
363
578k
        self.lookup(&mut enode).unwrap_or_else(|| {
364
578k
            let id = self.unionfind.make_set();
365
578k
            log::trace!("  ...adding to {}", id);
366
578k
            let class = Box::new(EClass {
367
578k
                id,
368
578k
                nodes: vec![enode.clone()],
369
578k
                data: N::make(self, &enode),
370
578k
                parents: Default::default(),
371
578k
            });
372
578k
373
578k
            // add this enode to the parent lists of its children
374
578k
            enode.for_each(|child| {
375
                let tup = (enode.clone(), id);
376
                self[child].parents.push(tup);
377
578k
            });
378
578k
379
578k
            assert_eq!(self.classes.len(), usize::from(id));
380
578k
            self.classes.push(Some(class));
381
578k
            assert!(self.memo.insert(enode, id).is_none());
382
383
578k
            N::modify(self, id);
384
578k
            id
385
578k
        })
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add::{closure#0}
386
1.62M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::add
Line
Count
Source
362
1.62M
    pub fn add(&mut self, mut enode: L) -> Id {
363
1.62M
        self.lookup(&mut enode).unwrap_or_else(|| {
364
            let id = self.unionfind.make_set();
365
            log::trace!("  ...adding to {}", id);
366
            let class = Box::new(EClass {
367
                id,
368
                nodes: vec![enode.clone()],
369
                data: N::make(self, &enode),
370
                parents: Default::default(),
371
            });
372
373
            // add this enode to the parent lists of its children
374
            enode.for_each(|child| {
375
                let tup = (enode.clone(), id);
376
                self[child].parents.push(tup);
377
            });
378
379
            assert_eq!(self.classes.len(), usize::from(id));
380
            self.classes.push(Some(class));
381
            assert!(self.memo.insert(enode, id).is_none());
382
383
            N::modify(self, id);
384
            id
385
1.62M
        })
386
1.62M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::add
387
388
    /// Checks whether two [`RecExpr`]s are equivalent.
389
    /// Returns a list of id where both expression are represented.
390
    /// In most cases, there will none or exactly one id.
391
    ///
392
    /// [`RecExpr`]: struct.RecExpr.html
393
0
    pub fn equivs(&self, expr1: &RecExpr<L>, expr2: &RecExpr<L>) -> Vec<Id> {
394
0
        let matches1 = Pattern::from(expr1.as_ref()).search(self);
395
0
        trace!("Matches1: {:?}", matches1);
396
397
0
        let matches2 = Pattern::from(expr2.as_ref()).search(self);
398
0
        trace!("Matches2: {:?}", matches2);
399
400
0
        let mut equiv_eclasses = Vec::new();
401
402
0
        for m1 in &matches1 {
403
0
            for m2 in &matches2 {
404
0
                if self.find(m1.eclass) == self.find(m2.eclass) {
405
0
                    equiv_eclasses.push(m1.eclass)
406
0
                }
407
            }
408
        }
409
410
0
        equiv_eclasses
411
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::equivs
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::equivs
412
413
    /// Panic if the given eclass doesn't contain the given patterns
414
    ///
415
    /// Useful for testing.
416
0
    pub fn check_goals(&self, id: Id, goals: &[Pattern<L>]) {
417
0
        let (cost, best) = Extractor::new(self, AstSize).find_best(id);
418
0
        println!("End ({}): {}", cost, best.pretty(80));
419
420
0
        for (i, goal) in goals.iter().enumerate() {
421
0
            println!("Trying to prove goal {}: {}", i, goal.pretty(40));
422
0
            let matches = goal.search_eclass(&self, id);
423
0
            if matches.is_none() {
424
0
                let best = Extractor::new(&self, AstSize).find_best(id).1;
425
0
                panic!(
426
0
                    "Could not prove goal {}:\n{}\nBest thing found:\n{}",
427
0
                    i,
428
0
                    goal.pretty(40),
429
0
                    best.pretty(40),
430
0
                );
431
0
            }
432
        }
433
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_goals
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_goals
434
435
    #[inline]
436
1.46M
    fn union_impl(&mut self, id1: Id, id2: Id) -> (Id, bool) {
437
1.46M
        fn concat<T>(to: &mut Vec<T>, mut from: Vec<T>) {
438
1.12M
            if to.len() < from.len() {
439
1.46M
                std::mem::swap(to, &mut from)
440
1.46M
            }
441
1.46M
            to.extend(from);
442
1.12M
        }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl::concat::<wasm_mutate::mutators::peephole::eggsy::lang::Lang>
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl::concat::<(wasm_mutate::mutators::peephole::eggsy::lang::Lang, egg::Id)>
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl::concat::<_>
<egg::egraph::EGraph<_, _>>::union_impl::concat::<wasm_mutate::mutators::peephole::eggsy::lang::Lang>
Line
Count
Source
437
561k
        fn concat<T>(to: &mut Vec<T>, mut from: Vec<T>) {
438
561k
            if to.len() < from.len() {
439
0
                std::mem::swap(to, &mut from)
440
561k
            }
441
561k
            to.extend(from);
442
561k
        }
<egg::egraph::EGraph<_, _>>::union_impl::concat::<(wasm_mutate::mutators::peephole::eggsy::lang::Lang, egg::Id)>
Line
Count
Source
437
561k
        fn concat<T>(to: &mut Vec<T>, mut from: Vec<T>) {
438
561k
            if to.len() < from.len() {
439
407
                std::mem::swap(to, &mut from)
440
560k
            }
441
561k
            to.extend(from);
442
561k
        }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl::concat::<_>
443
1.46M
444
1.46M
        let (to, from) = self.unionfind.union(id1, id2);
445
0
        debug_assert_eq!(to, self.find(id1));
446
0
        debug_assert_eq!(to, self.find(id2));
447
1.46M
        if to != from {
448
561k
            self.dirty_unions.push(to);
449
561k
450
561k
            // update the classes data structure
451
561k
            let from_class = self.classes[usize::from(from)].take().unwrap();
452
561k
            let to_class = self.classes[usize::from(to)].as_mut().unwrap();
453
561k
454
561k
            self.analysis.merge(&mut to_class.data, from_class.data);
455
561k
            concat(&mut to_class.nodes, from_class.nodes);
456
561k
            concat(&mut to_class.parents, from_class.parents);
457
561k
458
561k
            N::modify(self, to);
459
900k
        }
460
1.46M
        (to, to != from)
461
1.46M
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::union_impl
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::union_impl
Line
Count
Source
436
1.46M
    fn union_impl(&mut self, id1: Id, id2: Id) -> (Id, bool) {
437
1.46M
        fn concat<T>(to: &mut Vec<T>, mut from: Vec<T>) {
438
1.46M
            if to.len() < from.len() {
439
1.46M
                std::mem::swap(to, &mut from)
440
1.46M
            }
441
1.46M
            to.extend(from);
442
1.46M
        }
443
1.46M
444
1.46M
        let (to, from) = self.unionfind.union(id1, id2);
445
0
        debug_assert_eq!(to, self.find(id1));
446
0
        debug_assert_eq!(to, self.find(id2));
447
1.46M
        if to != from {
448
561k
            self.dirty_unions.push(to);
449
561k
450
561k
            // update the classes data structure
451
561k
            let from_class = self.classes[usize::from(from)].take().unwrap();
452
561k
            let to_class = self.classes[usize::from(to)].as_mut().unwrap();
453
561k
454
561k
            self.analysis.merge(&mut to_class.data, from_class.data);
455
561k
            concat(&mut to_class.nodes, from_class.nodes);
456
561k
            concat(&mut to_class.parents, from_class.parents);
457
561k
458
561k
            N::modify(self, to);
459
900k
        }
460
1.46M
        (to, to != from)
461
1.46M
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union_impl
462
463
    /// Unions two eclasses given their ids.
464
    ///
465
    /// The given ids need not be canonical.
466
    /// The returned `bool` indicates whether a union was done,
467
    /// so it's `false` if they were already equivalent.
468
    /// Both results are canonical.
469
765k
    pub fn union(&mut self, id1: Id, id2: Id) -> (Id, bool) {
470
765k
        let union = self.union_impl(id1, id2);
471
765k
        if union.1 && cfg!(feature = "upward-merging") {
472
0
            self.process_unions();
473
765k
        }
474
765k
        union
475
765k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::union
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::union
Line
Count
Source
469
765k
    pub fn union(&mut self, id1: Id, id2: Id) -> (Id, bool) {
470
765k
        let union = self.union_impl(id1, id2);
471
765k
        if union.1 && cfg!(feature = "upward-merging") {
472
0
            self.process_unions();
473
765k
        }
474
765k
        union
475
765k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::union
476
477
    /// Returns a more debug-able representation of the egraph.
478
    ///
479
    /// [`EGraph`]s implement [`Debug`], but it ain't pretty. It
480
    /// prints a lot of stuff you probably don't care about.
481
    /// This method returns a wrapper that implements [`Debug`] in a
482
    /// slightly nicer way, just dumping enodes in each eclass.
483
    ///
484
    /// [`Debug`]: https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html
485
    /// [`EGraph`]: struct.EGraph.html
486
0
    pub fn dump<'a>(&'a self) -> impl Debug + 'a {
487
0
        EGraphDump(self)
488
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::dump
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::dump
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::dump
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::dump
489
}
490
491
// All the rebuilding stuff
492
impl<L: Language, N: Analysis<L>> EGraph<L, N> {
493
    #[inline(never)]
494
5.37k
    fn rebuild_classes(&mut self) -> usize {
495
5.37k
        let mut classes_by_op = std::mem::take(&mut self.classes_by_op);
496
9.55k
        classes_by_op.values_mut().for_each(|ids| ids.clear());
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#0}
Line
Count
Source
496
9.55k
        classes_by_op.values_mut().for_each(|ids| ids.clear());
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#0}
497
5.37k
498
5.37k
        let mut trimmed = 0;
499
5.37k
500
5.37k
        let uf = &self.unionfind;
501
60.6k
        for class in self.classes.iter_mut().filter_map(Option::as_mut) {
502
60.6k
            let old_len = class.len();
503
60.6k
            class
504
60.6k
                .nodes
505
60.6k
                .iter_mut()
506
1.08M
                .for_each(|n| n.update_children(|id| uf.find(id)));
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#1}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#1}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#1}
Line
Count
Source
506
621k
                .for_each(|n| n.update_children(|id| uf.find(id)));
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#1}
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#1}::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#1}::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#1}::{closure#0}
Line
Count
Source
506
1.08M
                .for_each(|n| n.update_children(|id| uf.find(id)));
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#1}::{closure#0}
507
60.6k
            class.nodes.sort_unstable();
508
60.6k
            class.nodes.dedup();
509
60.6k
510
60.6k
            trimmed += old_len - class.nodes.len();
511
60.6k
512
60.6k
            // TODO this is the slow version, could take advantage of sortedness
513
60.6k
            // maybe
514
117k
            let mut add = |n: &L| {
515
117k
                #[allow(clippy::mem_discriminant_non_enum)]
516
117k
                classes_by_op
517
117k
                    .entry(std::mem::discriminant(&n))
518
117k
                    .or_default()
519
117k
                    .insert(class.id)
520
117k
            };
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#2}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#2}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes::{closure#2}
Line
Count
Source
514
117k
            let mut add = |n: &L| {
515
117k
                #[allow(clippy::mem_discriminant_non_enum)]
516
117k
                classes_by_op
517
117k
                    .entry(std::mem::discriminant(&n))
518
117k
                    .or_default()
519
117k
                    .insert(class.id)
520
117k
            };
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes::{closure#2}
521
522
            // we can go through the ops in order to dedup them, becaue we
523
            // just sorted them
524
60.6k
            let mut nodes = class.nodes.iter();
525
60.6k
            if let Some(mut prev) = nodes.next() {
526
60.6k
                add(prev);
527
144k
                for n in nodes {
528
83.9k
                    if !prev.matches(n) {
529
56.7k
                        add(n);
530
56.7k
                        prev = n;
531
56.7k
                    }
532
                }
533
0
            }
534
        }
535
536
        #[cfg(debug_assertions)]
537
        for ids in classes_by_op.values_mut() {
538
            let unique: indexmap::IndexSet<Id> = ids.iter().copied().collect();
539
            assert_eq!(ids.len(), unique.len());
540
        }
541
542
5.37k
        self.classes_by_op = classes_by_op;
543
5.37k
        trimmed
544
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild_classes
Line
Count
Source
494
5.37k
    fn rebuild_classes(&mut self) -> usize {
495
5.37k
        let mut classes_by_op = std::mem::take(&mut self.classes_by_op);
496
5.37k
        classes_by_op.values_mut().for_each(|ids| ids.clear());
497
5.37k
498
5.37k
        let mut trimmed = 0;
499
5.37k
500
5.37k
        let uf = &self.unionfind;
501
60.6k
        for class in self.classes.iter_mut().filter_map(Option::as_mut) {
502
60.6k
            let old_len = class.len();
503
60.6k
            class
504
60.6k
                .nodes
505
60.6k
                .iter_mut()
506
60.6k
                .for_each(|n| n.update_children(|id| uf.find(id)));
507
60.6k
            class.nodes.sort_unstable();
508
60.6k
            class.nodes.dedup();
509
60.6k
510
60.6k
            trimmed += old_len - class.nodes.len();
511
60.6k
512
60.6k
            // TODO this is the slow version, could take advantage of sortedness
513
60.6k
            // maybe
514
60.6k
            let mut add = |n: &L| {
515
                #[allow(clippy::mem_discriminant_non_enum)]
516
                classes_by_op
517
                    .entry(std::mem::discriminant(&n))
518
                    .or_default()
519
                    .insert(class.id)
520
            };
521
522
            // we can go through the ops in order to dedup them, becaue we
523
            // just sorted them
524
60.6k
            let mut nodes = class.nodes.iter();
525
60.6k
            if let Some(mut prev) = nodes.next() {
526
60.6k
                add(prev);
527
144k
                for n in nodes {
528
83.9k
                    if !prev.matches(n) {
529
56.7k
                        add(n);
530
56.7k
                        prev = n;
531
56.7k
                    }
532
                }
533
0
            }
534
        }
535
536
        #[cfg(debug_assertions)]
537
        for ids in classes_by_op.values_mut() {
538
            let unique: indexmap::IndexSet<Id> = ids.iter().copied().collect();
539
            assert_eq!(ids.len(), unique.len());
540
        }
541
542
5.37k
        self.classes_by_op = classes_by_op;
543
5.37k
        trimmed
544
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild_classes
545
546
    #[inline(never)]
547
0
    fn check_memo(&self) -> bool {
548
0
        let mut test_memo = IndexMap::new();
549
550
0
        for (id, class) in self.classes.iter().enumerate() {
551
0
            let id = Id::from(id);
552
0
            let class = match class.as_ref() {
553
0
                Some(class) => class,
554
0
                None => continue,
555
            };
556
0
            assert_eq!(class.id, id);
557
0
            for node in &class.nodes {
558
0
                if let Some(old) = test_memo.insert(node, id) {
559
0
                    assert_eq!(
560
0
                        self.find(old),
561
0
                        self.find(id),
562
0
                        "Found unexpected equivalence for {:?}\n{:?}\nvs\n{:?}",
563
0
                        node,
564
0
                        self[self.find(id)].nodes,
565
0
                        self[self.find(old)].nodes,
566
                    );
567
0
                }
568
            }
569
        }
570
571
0
        for (n, e) in test_memo {
572
0
            assert_eq!(e, self.find(e));
573
0
            assert_eq!(
574
0
                Some(e),
575
0
                self.memo.get(n).map(|id| self.find(*id)),
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::check_memo::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_memo::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::check_memo::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_memo::{closure#0}
576
0
                "Entry for {:?} at {} in test_memo was incorrect",
577
                n,
578
                e
579
            );
580
        }
581
582
0
        true
583
0
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::check_memo
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_memo
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::check_memo
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::check_memo
584
585
    #[inline(never)]
586
5.37k
    fn process_unions(&mut self) {
587
5.37k
        let mut to_union = vec![];
588
589
8.14k
        while !self.dirty_unions.is_empty() {
590
            // take the worklist, we'll get the stuff that's added the next time around
591
            // deduplicate the dirty list to avoid extra work
592
2.77k
            let mut todo = std::mem::take(&mut self.dirty_unions);
593
561k
            todo.iter_mut().for_each(|id| *id = self.find(*id));
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#0}
Line
Count
Source
593
561k
            todo.iter_mut().for_each(|id| *id = self.find(*id));
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#0}
594
2.77k
            if cfg!(not(feature = "upward-merging")) {
595
2.77k
                todo.sort_unstable();
596
2.77k
                todo.dedup();
597
2.77k
            }
598
2.77k
            assert!(!todo.is_empty());
599
600
8.27k
            for id in todo {
601
5.49k
                self.repairs_since_rebuild += 1;
602
5.49k
                let mut parents = std::mem::take(&mut self[id].parents);
603
604
779k
                for (n, _e) in &parents {
605
774k
                    self.memo.remove(n);
606
774k
                }
607
608
774k
                parents.iter_mut().for_each(|(n, id)| {
609
1.48M
                    n.update_children(|child| self.find(child));
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#1}::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#1}::{closure#0}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#1}::{closure#0}
Line
Count
Source
609
1.48M
                    n.update_children(|child| self.find(child));
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#1}::{closure#0}
610
774k
                    *id = self.find(*id);
611
774k
                });
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#1}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#1}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#1}
Line
Count
Source
608
774k
                parents.iter_mut().for_each(|(n, id)| {
609
774k
                    n.update_children(|child| self.find(child));
610
774k
                    *id = self.find(*id);
611
774k
                });
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#1}
612
5.49k
                parents.sort_unstable();
613
5.49k
                parents.dedup_by(|(n1, e1), (n2, e2)| {
614
768k
                    n1 == n2 && {
615
695k
                        to_union.push((*e1, *e2));
616
695k
                        true
617
                    }
618
768k
                });
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#2}
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#2}
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions::{closure#2}
Line
Count
Source
614
768k
                    n1 == n2 && {
615
695k
                        to_union.push((*e1, *e2));
616
695k
                        true
617
                    }
618
768k
                });
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions::{closure#2}
619
620
83.6k
                for (n, e) in &parents {
621
78.1k
                    if let Some(old) = self.memo.insert(n.clone(), *e) {
622
258
                        to_union.push((old, *e));
623
77.9k
                    }
624
                }
625
626
5.49k
                self.propagate_metadata(&parents);
627
5.49k
628
5.49k
                self[id].parents = parents;
629
5.49k
                N::modify(self, id);
630
            }
631
632
696k
            for (id1, id2) in to_union.drain(..) {
633
696k
                let (to, did_something) = self.union_impl(id1, id2);
634
696k
                if did_something {
635
608
                    self.dirty_unions.push(to);
636
695k
                }
637
            }
638
        }
639
640
5.37k
        assert!(self.dirty_unions.is_empty());
641
5.37k
        assert!(to_union.is_empty());
642
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::process_unions
Line
Count
Source
586
5.37k
    fn process_unions(&mut self) {
587
5.37k
        let mut to_union = vec![];
588
589
8.14k
        while !self.dirty_unions.is_empty() {
590
            // take the worklist, we'll get the stuff that's added the next time around
591
            // deduplicate the dirty list to avoid extra work
592
2.77k
            let mut todo = std::mem::take(&mut self.dirty_unions);
593
2.77k
            todo.iter_mut().for_each(|id| *id = self.find(*id));
594
2.77k
            if cfg!(not(feature = "upward-merging")) {
595
2.77k
                todo.sort_unstable();
596
2.77k
                todo.dedup();
597
2.77k
            }
598
2.77k
            assert!(!todo.is_empty());
599
600
8.27k
            for id in todo {
601
5.49k
                self.repairs_since_rebuild += 1;
602
5.49k
                let mut parents = std::mem::take(&mut self[id].parents);
603
604
779k
                for (n, _e) in &parents {
605
774k
                    self.memo.remove(n);
606
774k
                }
607
608
5.49k
                parents.iter_mut().for_each(|(n, id)| {
609
                    n.update_children(|child| self.find(child));
610
                    *id = self.find(*id);
611
5.49k
                });
612
5.49k
                parents.sort_unstable();
613
5.49k
                parents.dedup_by(|(n1, e1), (n2, e2)| {
614
                    n1 == n2 && {
615
                        to_union.push((*e1, *e2));
616
                        true
617
                    }
618
5.49k
                });
619
620
83.6k
                for (n, e) in &parents {
621
78.1k
                    if let Some(old) = self.memo.insert(n.clone(), *e) {
622
258
                        to_union.push((old, *e));
623
77.9k
                    }
624
                }
625
626
5.49k
                self.propagate_metadata(&parents);
627
5.49k
628
5.49k
                self[id].parents = parents;
629
5.49k
                N::modify(self, id);
630
            }
631
632
696k
            for (id1, id2) in to_union.drain(..) {
633
696k
                let (to, did_something) = self.union_impl(id1, id2);
634
696k
                if did_something {
635
608
                    self.dirty_unions.push(to);
636
695k
                }
637
            }
638
        }
639
640
5.37k
        assert!(self.dirty_unions.is_empty());
641
5.37k
        assert!(to_union.is_empty());
642
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::process_unions
643
644
    /// Restores the egraph invariants of congruence and enode uniqueness.
645
    ///
646
    /// As mentioned [above](struct.EGraph.html#invariants-and-rebuilding),
647
    /// `egg` takes a lazy approach to maintaining the egraph invariants.
648
    /// The `rebuild` method allows the user to manually restore those
649
    /// invariants at a time of their choosing. It's a reasonably
650
    /// fast, linear-ish traversal through the egraph.
651
    ///
652
    /// # Example
653
    /// ```
654
    /// use egg::{*, SymbolLang as S};
655
    /// let mut egraph = EGraph::<S, ()>::default();
656
    /// let x = egraph.add(S::leaf("x"));
657
    /// let y = egraph.add(S::leaf("y"));
658
    /// let ax = egraph.add_expr(&"(+ a x)".parse().unwrap());
659
    /// let ay = egraph.add_expr(&"(+ a y)".parse().unwrap());
660
    ///
661
    /// // The effects of this union aren't yet visible; ax and ay
662
    /// // should be equivalent by congruence since x = y.
663
    /// egraph.union(x, y);
664
    /// // Classes: [x y] [ax] [ay] [a]
665
    /// # #[cfg(not(feature = "upward-merging"))]
666
    /// assert_eq!(egraph.number_of_classes(), 4);
667
    /// # #[cfg(not(feature = "upward-merging"))]
668
    /// assert_ne!(egraph.find(ax), egraph.find(ay));
669
    ///
670
    /// // Rebuilding restores the invariants, finding the "missing" equivalence
671
    /// egraph.rebuild();
672
    /// // Classes: [x y] [ax ay] [a]
673
    /// assert_eq!(egraph.number_of_classes(), 3);
674
    /// assert_eq!(egraph.find(ax), egraph.find(ay));
675
    /// ```
676
5.37k
    pub fn rebuild(&mut self) -> usize {
677
5.37k
        let old_hc_size = self.memo.len();
678
5.37k
        let old_n_eclasses = self.number_of_classes();
679
5.37k
680
5.37k
        let start = instant::Instant::now();
681
5.37k
682
5.37k
        self.process_unions();
683
5.37k
        let n_unions = std::mem::take(&mut self.repairs_since_rebuild);
684
5.37k
        let trimmed_nodes = self.rebuild_classes();
685
5.37k
686
5.37k
        let elapsed = start.elapsed();
687
5.37k
        info!(
688
0
            concat!(
689
0
                "REBUILT! in {}.{:03}s\n",
690
0
                "  Old: hc size {}, eclasses: {}\n",
691
0
                "  New: hc size {}, eclasses: {}\n",
692
0
                "  unions: {}, trimmed nodes: {}"
693
0
            ),
694
0
            elapsed.as_secs(),
695
0
            elapsed.subsec_millis(),
696
0
            old_hc_size,
697
0
            old_n_eclasses,
698
0
            self.memo.len(),
699
0
            self.number_of_classes(),
700
            n_unions,
701
            trimmed_nodes,
702
        );
703
704
0
        debug_assert!(self.check_memo());
705
5.37k
        n_unions
706
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::rebuild
Line
Count
Source
676
5.37k
    pub fn rebuild(&mut self) -> usize {
677
5.37k
        let old_hc_size = self.memo.len();
678
5.37k
        let old_n_eclasses = self.number_of_classes();
679
5.37k
680
5.37k
        let start = instant::Instant::now();
681
5.37k
682
5.37k
        self.process_unions();
683
5.37k
        let n_unions = std::mem::take(&mut self.repairs_since_rebuild);
684
5.37k
        let trimmed_nodes = self.rebuild_classes();
685
5.37k
686
5.37k
        let elapsed = start.elapsed();
687
5.37k
        info!(
688
0
            concat!(
689
0
                "REBUILT! in {}.{:03}s\n",
690
0
                "  Old: hc size {}, eclasses: {}\n",
691
0
                "  New: hc size {}, eclasses: {}\n",
692
0
                "  unions: {}, trimmed nodes: {}"
693
0
            ),
694
0
            elapsed.as_secs(),
695
0
            elapsed.subsec_millis(),
696
0
            old_hc_size,
697
0
            old_n_eclasses,
698
0
            self.memo.len(),
699
0
            self.number_of_classes(),
700
            n_unions,
701
            trimmed_nodes,
702
        );
703
704
0
        debug_assert!(self.check_memo());
705
5.37k
        n_unions
706
5.37k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::rebuild
707
708
    #[inline(never)]
709
5.49k
    fn propagate_metadata(&mut self, parents: &[(L, Id)]) {
710
83.6k
        for (n, e) in parents {
711
78.1k
            let e = self.find(*e);
712
78.1k
            let node_data = N::make(self, n);
713
78.1k
            let class = self.classes[usize::from(e)].as_mut().unwrap();
714
78.1k
            if self.analysis.merge(&mut class.data, node_data) {
715
                // self.dirty_unions.push(e); // NOTE: i dont think this is necessary
716
0
                let e_parents = std::mem::take(&mut class.parents);
717
0
                self.propagate_metadata(&e_parents);
718
0
                self[e].parents = e_parents;
719
0
                N::modify(self, e)
720
78.1k
            }
721
        }
722
5.49k
    }
Unexecuted instantiation: <egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::propagate_metadata
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::propagate_metadata
<egg::egraph::EGraph<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis>>::propagate_metadata
Line
Count
Source
709
5.49k
    fn propagate_metadata(&mut self, parents: &[(L, Id)]) {
710
83.6k
        for (n, e) in parents {
711
78.1k
            let e = self.find(*e);
712
78.1k
            let node_data = N::make(self, n);
713
78.1k
            let class = self.classes[usize::from(e)].as_mut().unwrap();
714
78.1k
            if self.analysis.merge(&mut class.data, node_data) {
715
                // self.dirty_unions.push(e); // NOTE: i dont think this is necessary
716
0
                let e_parents = std::mem::take(&mut class.parents);
717
0
                self.propagate_metadata(&e_parents);
718
0
                self[e].parents = e_parents;
719
0
                N::modify(self, e)
720
78.1k
            }
721
        }
722
5.49k
    }
Unexecuted instantiation: <egg::egraph::EGraph<_, _>>::propagate_metadata
723
}
724
725
struct EGraphDump<'a, L: Language, N: Analysis<L>>(&'a EGraph<L, N>);
726
727
impl<'a, L: Language, N: Analysis<L>> Debug for EGraphDump<'a, L, N> {
728
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
729
0
        let mut ids: Vec<Id> = self.0.classes().map(|c| c.id).collect();
Unexecuted instantiation: <egg::egraph::EGraphDump<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::fmt::Debug>::fmt::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraphDump<_, _> as core::fmt::Debug>::fmt::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraphDump<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::fmt::Debug>::fmt::{closure#0}
Unexecuted instantiation: <egg::egraph::EGraphDump<_, _> as core::fmt::Debug>::fmt::{closure#0}
730
0
        ids.sort();
731
0
        for id in ids {
732
0
            let mut nodes = self.0[id].nodes.clone();
733
0
            nodes.sort();
734
0
            writeln!(f, "{}: {:?}", id, nodes)?
735
        }
736
0
        Ok(())
737
0
    }
Unexecuted instantiation: <egg::egraph::EGraphDump<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::fmt::Debug>::fmt
Unexecuted instantiation: <egg::egraph::EGraphDump<_, _> as core::fmt::Debug>::fmt
Unexecuted instantiation: <egg::egraph::EGraphDump<wasm_mutate::mutators::peephole::eggsy::lang::Lang, wasm_mutate::mutators::peephole::eggsy::analysis::PeepholeMutationAnalysis> as core::fmt::Debug>::fmt
Unexecuted instantiation: <egg::egraph::EGraphDump<_, _> as core::fmt::Debug>::fmt
738
}
739
740
#[cfg(test)]
741
mod tests {
742
743
    use crate::*;
744
745
    #[test]
746
    fn simple_add() {
747
        use SymbolLang as S;
748
749
        crate::init_logger();
750
        let mut egraph = EGraph::<S, ()>::default();
751
752
        let x = egraph.add(S::leaf("x"));
753
        let x2 = egraph.add(S::leaf("x"));
754
        let _plus = egraph.add(S::new("+", vec![x, x2]));
755
756
        let y = egraph.add(S::leaf("y"));
757
758
        egraph.union(x, y);
759
        egraph.rebuild();
760
761
        egraph.dot().to_dot("target/foo.dot").unwrap();
762
763
        assert_eq!(2 + 2, 4);
764
    }
765
}