11#![ deny( rustc:: untranslatable_diagnostic) ]
22#![ deny( rustc:: diagnostic_outside_of_impl) ]
3+ use rustc_data_structures:: fx:: FxHashSet ;
34use rustc_data_structures:: fx:: FxIndexSet ;
45use rustc_index:: bit_set:: SparseBitMatrix ;
56use rustc_index:: interval:: IntervalSet ;
@@ -125,8 +126,15 @@ pub(crate) struct LivenessValues {
125126 /// The map from locations to points.
126127 elements : Rc < RegionValueElements > ,
127128
129+ /// Which regions are live. This is exclusive with the fine-grained tracking in `points`, and
130+ /// currently only used for validating promoteds (which don't care about more precise tracking).
131+ live_regions : Option < FxHashSet < RegionVid > > ,
132+
128133 /// For each region: the points where it is live.
129- points : SparseIntervalMatrix < RegionVid , PointIndex > ,
134+ ///
135+ /// This is not initialized for promoteds, because we don't care *where* within a promoted a
136+ /// region is live, only that it is.
137+ points : Option < SparseIntervalMatrix < RegionVid , PointIndex > > ,
130138
131139 /// When using `-Zpolonius=next`, for each point: the loans flowing into the live regions at
132140 /// that point.
@@ -155,24 +163,52 @@ impl LiveLoans {
155163
156164impl LivenessValues {
157165 /// Create an empty map of regions to locations where they're live.
158- pub ( crate ) fn new ( elements : Rc < RegionValueElements > ) -> Self {
166+ pub ( crate ) fn with_specific_points ( elements : Rc < RegionValueElements > ) -> Self {
159167 LivenessValues {
160- points : SparseIntervalMatrix :: new ( elements. num_points ) ,
168+ live_regions : None ,
169+ points : Some ( SparseIntervalMatrix :: new ( elements. num_points ) ) ,
170+ elements,
171+ loans : None ,
172+ }
173+ }
174+
175+ /// Create an empty map of regions to locations where they're live.
176+ ///
177+ /// Unlike `with_specific_points`, does not track exact locations where something is live, only
178+ /// which regions are live.
179+ pub ( crate ) fn without_specific_points ( elements : Rc < RegionValueElements > ) -> Self {
180+ LivenessValues {
181+ live_regions : Some ( Default :: default ( ) ) ,
182+ points : None ,
161183 elements,
162184 loans : None ,
163185 }
164186 }
165187
166188 /// Iterate through each region that has a value in this set.
167- pub ( crate ) fn regions ( & self ) -> impl Iterator < Item = RegionVid > {
168- self . points . rows ( )
189+ pub ( crate ) fn regions ( & self ) -> impl Iterator < Item = RegionVid > + ' _ {
190+ self . points . as_ref ( ) . expect ( "use with_specific_points" ) . rows ( )
191+ }
192+
193+ /// Iterate through each region that has a value in this set.
194+ // We are passing query instability implications to the caller.
195+ #[ rustc_lint_query_instability]
196+ #[ allow( rustc:: potential_query_instability) ]
197+ pub ( crate ) fn live_regions_unordered ( & self ) -> impl Iterator < Item = RegionVid > + ' _ {
198+ self . live_regions . as_ref ( ) . unwrap ( ) . iter ( ) . copied ( )
169199 }
170200
171201 /// Records `region` as being live at the given `location`.
172202 pub ( crate ) fn add_location ( & mut self , region : RegionVid , location : Location ) {
173- debug ! ( "LivenessValues::add_location(region={:?}, location={:?})" , region, location) ;
174203 let point = self . elements . point_from_location ( location) ;
175- self . points . insert ( region, point) ;
204+ debug ! ( "LivenessValues::add_location(region={:?}, location={:?})" , region, location) ;
205+ if let Some ( points) = & mut self . points {
206+ points. insert ( region, point) ;
207+ } else {
208+ if self . elements . point_in_range ( point) {
209+ self . live_regions . as_mut ( ) . unwrap ( ) . insert ( region) ;
210+ }
211+ }
176212
177213 // When available, record the loans flowing into this region as live at the given point.
178214 if let Some ( loans) = self . loans . as_mut ( ) {
@@ -185,7 +221,13 @@ impl LivenessValues {
185221 /// Records `region` as being live at all the given `points`.
186222 pub ( crate ) fn add_points ( & mut self , region : RegionVid , points : & IntervalSet < PointIndex > ) {
187223 debug ! ( "LivenessValues::add_points(region={:?}, points={:?})" , region, points) ;
188- self . points . union_row ( region, points) ;
224+ if let Some ( this) = & mut self . points {
225+ this. union_row ( region, points) ;
226+ } else {
227+ if points. iter ( ) . any ( |point| self . elements . point_in_range ( point) ) {
228+ self . live_regions . as_mut ( ) . unwrap ( ) . insert ( region) ;
229+ }
230+ }
189231
190232 // When available, record the loans flowing into this region as live at the given points.
191233 if let Some ( loans) = self . loans . as_mut ( ) {
@@ -201,23 +243,33 @@ impl LivenessValues {
201243
202244 /// Records `region` as being live at all the control-flow points.
203245 pub ( crate ) fn add_all_points ( & mut self , region : RegionVid ) {
204- self . points . insert_all_into_row ( region) ;
246+ if let Some ( points) = & mut self . points {
247+ points. insert_all_into_row ( region) ;
248+ } else {
249+ self . live_regions . as_mut ( ) . unwrap ( ) . insert ( region) ;
250+ }
205251 }
206252
207253 /// Returns whether `region` is marked live at the given `location`.
208254 pub ( crate ) fn is_live_at ( & self , region : RegionVid , location : Location ) -> bool {
209255 let point = self . elements . point_from_location ( location) ;
210- self . points . row ( region) . is_some_and ( |r| r. contains ( point) )
211- }
212-
213- /// Returns whether `region` is marked live at any location.
214- pub ( crate ) fn is_live_anywhere ( & self , region : RegionVid ) -> bool {
215- self . live_points ( region) . next ( ) . is_some ( )
256+ if let Some ( points) = & self . points {
257+ points. row ( region) . is_some_and ( |r| r. contains ( point) )
258+ } else {
259+ unreachable ! (
260+ "Should be using LivenessValues::with_specific_points to ask whether live at a location"
261+ )
262+ }
216263 }
217264
218265 /// Returns an iterator of all the points where `region` is live.
219266 fn live_points ( & self , region : RegionVid ) -> impl Iterator < Item = PointIndex > + ' _ {
220- self . points
267+ let Some ( points) = & self . points else {
268+ unreachable ! (
269+ "Should be using LivenessValues::with_specific_points to ask whether live at a location"
270+ )
271+ } ;
272+ points
221273 . row ( region)
222274 . into_iter ( )
223275 . flat_map ( |set| set. iter ( ) )
@@ -372,7 +424,10 @@ impl<N: Idx> RegionValues<N> {
372424 /// elements for the region `from` from `values` and add them to
373425 /// the region `to` in `self`.
374426 pub ( crate ) fn merge_liveness ( & mut self , to : N , from : RegionVid , values : & LivenessValues ) {
375- if let Some ( set) = values. points . row ( from) {
427+ let Some ( value_points) = & values. points else {
428+ panic ! ( "LivenessValues must track specific points for use in merge_liveness" ) ;
429+ } ;
430+ if let Some ( set) = value_points. row ( from) {
376431 self . points . union_row ( to, set) ;
377432 }
378433 }
0 commit comments