]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | // Copyright 2019 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
60c5eb7d | 11 | //! An implementation of the origin liveness calculation logic |
416331ca XL |
12 | |
13 | use std::collections::BTreeSet; | |
14 | use std::time::Instant; | |
15 | ||
60c5eb7d XL |
16 | use crate::facts::FactTypes; |
17 | use crate::output::{LivenessContext, Output}; | |
416331ca XL |
18 | |
19 | use datafrog::{Iteration, Relation, RelationLeaper}; | |
20 | ||
60c5eb7d XL |
21 | pub(super) fn compute_live_regions<T: FactTypes>( |
22 | ctx: LivenessContext<T>, | |
23 | cfg_edge_rel: &Relation<(T::Point, T::Point)>, | |
24 | var_maybe_initialized_on_exit_rel: Relation<(T::Variable, T::Point)>, | |
25 | output: &mut Output<T>, | |
26 | ) -> Vec<(T::Origin, T::Point)> { | |
27 | let timer = Instant::now(); | |
416331ca XL |
28 | let mut iteration = Iteration::new(); |
29 | ||
30 | // Relations | |
60c5eb7d XL |
31 | let var_defined_rel: Relation<(T::Variable, T::Point)> = ctx.var_defined.into(); |
32 | let cfg_edge_reverse_rel: Relation<(T::Point, T::Point)> = cfg_edge_rel | |
33 | .iter() | |
34 | .map(|&(point1, point2)| (point2, point1)) | |
35 | .collect(); | |
36 | let var_uses_region_rel: Relation<(T::Variable, T::Origin)> = ctx.var_uses_region.into(); | |
37 | let var_drops_region_rel: Relation<(T::Variable, T::Origin)> = ctx.var_drops_region.into(); | |
38 | let var_drop_used_rel: Relation<((T::Variable, T::Point), ())> = ctx | |
39 | .var_drop_used | |
e1599b0c | 40 | .into_iter() |
60c5eb7d | 41 | .map(|(var, point)| ((var, point), ())) |
e1599b0c | 42 | .collect(); |
416331ca XL |
43 | |
44 | // Variables | |
45 | ||
60c5eb7d XL |
46 | // `var_live`: variable `var` is live upon entry at `point` |
47 | let var_live_var = iteration.variable::<(T::Variable, T::Point)>("var_live_at"); | |
48 | // `var_drop_live`: variable `var` is drop-live (will be used for a drop) upon entry in `point` | |
49 | let var_drop_live_var = iteration.variable::<(T::Variable, T::Point)>("var_drop_live_at"); | |
416331ca XL |
50 | |
51 | // This is what we are actually calculating: | |
60c5eb7d | 52 | let region_live_at_var = iteration.variable::<(T::Origin, T::Point)>("region_live_at"); |
416331ca | 53 | |
60c5eb7d XL |
54 | // This propagates the relation `var_live(var, point) :- var_used(var, point)`: |
55 | var_live_var.insert(ctx.var_used.into()); | |
416331ca | 56 | |
60c5eb7d XL |
57 | // var_maybe_initialized_on_entry(var, point2) :- |
58 | // var_maybe_initialized_on_exit(var, point1), | |
59 | // cfg_edge(point1, point2). | |
e1599b0c XL |
60 | let var_maybe_initialized_on_entry = Relation::from_leapjoin( |
61 | &var_maybe_initialized_on_exit_rel, | |
60c5eb7d XL |
62 | cfg_edge_rel.extend_with(|&(_var, point1)| point1), |
63 | |&(var, _point1), &point2| ((var, point2), ()), | |
e1599b0c XL |
64 | ); |
65 | ||
60c5eb7d XL |
66 | // var_drop_live(var, point) :- |
67 | // var_drop_used(var, point), | |
68 | // var_maybe_initialzed_on_entry(var, point). | |
e1599b0c XL |
69 | var_drop_live_var.insert(Relation::from_join( |
70 | &var_drop_used_rel, | |
71 | &var_maybe_initialized_on_entry, | |
60c5eb7d | 72 | |&(var, point), _, _| (var, point), |
e1599b0c | 73 | )); |
416331ca XL |
74 | |
75 | while iteration.changed() { | |
60c5eb7d XL |
76 | // region_live_at(origin, point) :- |
77 | // var_drop_live(var, point), | |
78 | // var_drops_region(var, origin). | |
79 | region_live_at_var.from_join( | |
80 | &var_drop_live_var, | |
81 | &var_drops_region_rel, | |
82 | |_var, &point, &origin| (origin, point), | |
83 | ); | |
84 | ||
85 | // region_live_at(origin, point) :- | |
86 | // var_live(var, point), | |
87 | // var_uses_region(var, origin). | |
88 | region_live_at_var.from_join( | |
89 | &var_live_var, | |
90 | &var_uses_region_rel, | |
91 | |_var, &point, &origin| (origin, point), | |
92 | ); | |
93 | ||
94 | // var_live(var, point1) :- | |
95 | // var_live(var, point2), | |
96 | // cfg_edge(point1, point2), | |
97 | // !var_defined(var, point1). | |
416331ca XL |
98 | var_live_var.from_leapjoin( |
99 | &var_live_var, | |
100 | ( | |
60c5eb7d XL |
101 | var_defined_rel.extend_anti(|&(var, _point2)| var), |
102 | cfg_edge_reverse_rel.extend_with(|&(_var, point2)| point2), | |
416331ca | 103 | ), |
60c5eb7d | 104 | |&(var, _point2), &point1| (var, point1), |
416331ca XL |
105 | ); |
106 | ||
60c5eb7d XL |
107 | // var_drop_live(var, point1) :- |
108 | // var_drop_live(var, point2), | |
109 | // cfg_edge(point1, point2), | |
110 | // !var_defined(var, point1) | |
111 | // var_maybe_initialized_on_exit(var, point1). | |
112 | // | |
113 | // Extend `point1` with `var:s` from `point2` such that `var` is not in `point2`, | |
114 | // there is an edge from `point1` to `point2` | |
416331ca XL |
115 | var_drop_live_var.from_leapjoin( |
116 | &var_drop_live_var, | |
117 | ( | |
60c5eb7d XL |
118 | var_defined_rel.extend_anti(|&(var, _point2)| var), |
119 | cfg_edge_reverse_rel.extend_with(|&(_var, point2)| point2), | |
120 | var_maybe_initialized_on_exit_rel.extend_with(|&(var, _point2)| var), | |
416331ca | 121 | ), |
60c5eb7d | 122 | |&(var, _point2), &point1| (var, point1), |
416331ca XL |
123 | ); |
124 | } | |
125 | ||
60c5eb7d | 126 | let region_live_at = region_live_at_var.complete(); |
416331ca XL |
127 | |
128 | info!( | |
60c5eb7d XL |
129 | "compute_live_regions() completed: {} tuples, {:?}", |
130 | region_live_at.len(), | |
131 | timer.elapsed(), | |
416331ca XL |
132 | ); |
133 | ||
134 | if output.dump_enabled { | |
135 | let var_drop_live_at = var_drop_live_var.complete(); | |
60c5eb7d | 136 | for &(var, location) in var_drop_live_at.iter() { |
416331ca XL |
137 | output |
138 | .var_drop_live_at | |
139 | .entry(location) | |
60c5eb7d | 140 | .or_default() |
416331ca XL |
141 | .push(var); |
142 | } | |
143 | ||
144 | let var_live_at = var_live_var.complete(); | |
60c5eb7d XL |
145 | for &(var, location) in var_live_at.iter() { |
146 | output.var_live_at.entry(location).or_default().push(var); | |
416331ca XL |
147 | } |
148 | } | |
149 | ||
60c5eb7d | 150 | region_live_at.elements |
416331ca XL |
151 | } |
152 | ||
60c5eb7d XL |
153 | pub(super) fn make_universal_regions_live<T: FactTypes>( |
154 | region_live_at: &mut Vec<(T::Origin, T::Point)>, | |
155 | cfg_node: &BTreeSet<T::Point>, | |
156 | universal_regions: &[T::Origin], | |
416331ca XL |
157 | ) { |
158 | debug!("make_universal_regions_live()"); | |
159 | ||
60c5eb7d XL |
160 | region_live_at.reserve(universal_regions.len() * cfg_node.len()); |
161 | for &origin in universal_regions.iter() { | |
162 | for &point in cfg_node.iter() { | |
163 | region_live_at.push((origin, point)); | |
416331ca XL |
164 | } |
165 | } | |
166 | } |