]> git.proxmox.com Git - rustc.git/blame - vendor/polonius-engine/src/output/liveness.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / vendor / polonius-engine / src / output / liveness.rs
CommitLineData
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
13use std::collections::BTreeSet;
14use std::time::Instant;
15
60c5eb7d
XL
16use crate::facts::FactTypes;
17use crate::output::{LivenessContext, Output};
416331ca
XL
18
19use datafrog::{Iteration, Relation, RelationLeaper};
20
60c5eb7d
XL
21pub(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
153pub(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}