Skip to content

Commit 0335ce8

Browse files
committed
Simplify condition graph.
1 parent 144173d commit 0335ce8

12 files changed

+231
-291
lines changed

compiler/rustc_mir_transform/src/jump_threading.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
134134
finder.entry_states[bb] = state;
135135
}
136136

137-
if let Some(opportunities) = OpportunitySet::new(body, finder.entry_states) {
137+
let mut entry_states = finder.entry_states;
138+
simplify_conditions(body, &mut entry_states);
139+
140+
if let Some(opportunities) = OpportunitySet::new(body, entry_states) {
138141
opportunities.apply();
139142
}
140143
}
@@ -782,6 +785,91 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
782785
}
783786
}
784787

788+
/// Propagate fulfilled conditions forward in the CFG to reduce the amount of duplication.
789+
#[instrument(level = "debug", skip(body, entry_states))]
790+
fn simplify_conditions(body: &Body<'_>, entry_states: &mut IndexVec<BasicBlock, ConditionSet>) {
791+
let basic_blocks = &body.basic_blocks;
792+
let reverse_postorder = basic_blocks.reverse_postorder();
793+
794+
// Start by computing the number of *incoming edges* for each block.
795+
// We do not use the cached `basic_blocks.predecessors` as we only want reachable predecessors.
796+
let mut predecessors = IndexVec::from_elem(0, &entry_states);
797+
predecessors[START_BLOCK] = 1; // Account for the implicit entry edge.
798+
for &bb in reverse_postorder {
799+
let term = basic_blocks[bb].terminator();
800+
for s in term.successors() {
801+
predecessors[s] += 1;
802+
}
803+
}
804+
805+
// Compute the number of edges into each block that carry each condition.
806+
let mut fulfill_in_pred_count = IndexVec::from_fn_n(
807+
|bb: BasicBlock| IndexVec::from_elem_n(0, entry_states[bb].targets.len()),
808+
entry_states.len(),
809+
);
810+
811+
// By traversing in RPO, we increase the likelihood to visit predecessors before successors.
812+
for &bb in reverse_postorder {
813+
let preds = predecessors[bb];
814+
trace!(?bb, ?preds);
815+
816+
// We have removed all the input edges towards this block. Just skip visiting it.
817+
if preds == 0 {
818+
continue;
819+
}
820+
821+
let state = &mut entry_states[bb];
822+
trace!(?state);
823+
824+
// Conditions that are fulfilled in all the predecessors, are fulfilled in `bb`.
825+
trace!(fulfilled_count = ?fulfill_in_pred_count[bb]);
826+
for (condition, &cond_preds) in fulfill_in_pred_count[bb].iter_enumerated() {
827+
if cond_preds == preds {
828+
trace!(?condition);
829+
state.fulfilled.push(condition);
830+
}
831+
}
832+
833+
// We want to count how many times each condition is fulfilled,
834+
// so ensure we are not counting the same edge twice.
835+
let mut targets: Vec<_> = state
836+
.fulfilled
837+
.iter()
838+
.flat_map(|&index| state.targets[index].iter().copied())
839+
.collect();
840+
targets.sort();
841+
targets.dedup();
842+
trace!(?targets);
843+
844+
// We may modify the set of successors by applying edges, so track them here.
845+
let mut successors = basic_blocks[bb].terminator().successors().collect::<Vec<_>>();
846+
847+
targets.reverse();
848+
while let Some(target) = targets.pop() {
849+
match target {
850+
EdgeEffect::Goto { target } => {
851+
// We update the count of predecessors. If target or any successor has not been
852+
// processed yet, this increases the likelihood we find something relevant.
853+
predecessors[target] += 1;
854+
for &s in successors.iter() {
855+
predecessors[s] -= 1;
856+
}
857+
// Only process edges that still exist.
858+
targets.retain(|t| t.block() == target);
859+
successors.clear();
860+
successors.push(target);
861+
}
862+
EdgeEffect::Chain { succ_block, succ_condition } => {
863+
// `predecessors` is the number of incoming *edges* in each block.
864+
// Count the number of edges that apply `succ_condition` into `succ_block`.
865+
let count = successors.iter().filter(|&&s| s == succ_block).count();
866+
fulfill_in_pred_count[succ_block][succ_condition] += count;
867+
}
868+
}
869+
}
870+
}
871+
}
872+
785873
struct OpportunitySet<'a, 'tcx> {
786874
basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
787875
entry_states: IndexVec<BasicBlock, ConditionSet>,

tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@
6161
_22 = const true;
6262
_23 = const true;
6363
_4 = discriminant(_2);
64-
- switchInt(move _4) -> [0: bb3, 1: bb4, otherwise: bb2];
65-
+ switchInt(move _4) -> [0: bb21, 1: bb4, otherwise: bb2];
64+
switchInt(move _4) -> [0: bb3, 1: bb4, otherwise: bb2];
6665
}
6766

6867
bb2: {
@@ -71,7 +70,8 @@
7170

7271
bb3: {
7372
_1 = chained_conditions::BacktraceStyle::Off;
74-
goto -> bb18;
73+
- goto -> bb18;
74+
+ goto -> bb35;
7575
}
7676

7777
bb4: {
@@ -101,8 +101,7 @@
101101
_23 = const false;
102102
_5 = move ((_2 as Some).0: std::string::String);
103103
_1 = chained_conditions::BacktraceStyle::Full;
104-
- drop(_5) -> [return: bb7, unwind unreachable];
105-
+ drop(_5) -> [return: bb23, unwind unreachable];
104+
drop(_5) -> [return: bb7, unwind unreachable];
106105
}
107106

108107
bb6: {
@@ -131,7 +130,8 @@
131130
bb7: {
132131
StorageDead(_5);
133132
StorageDead(_6);
134-
goto -> bb18;
133+
- goto -> bb18;
134+
+ goto -> bb22;
135135
}
136136

137137
bb8: {
@@ -143,8 +143,7 @@
143143
_23 = const false;
144144
_12 = move ((_2 as Some).0: std::string::String);
145145
_1 = chained_conditions::BacktraceStyle::Off;
146-
- drop(_12) -> [return: bb10, unwind unreachable];
147-
+ drop(_12) -> [return: bb30, unwind unreachable];
146+
drop(_12) -> [return: bb10, unwind unreachable];
148147
}
149148

150149
bb9: {
@@ -155,13 +154,14 @@
155154
StorageDead(_13);
156155
_1 = chained_conditions::BacktraceStyle::Short;
157156
- goto -> bb18;
158-
+ goto -> bb36;
157+
+ goto -> bb31;
159158
}
160159

161160
bb10: {
162161
StorageDead(_12);
163162
StorageDead(_13);
164-
goto -> bb18;
163+
- goto -> bb18;
164+
+ goto -> bb27;
165165
}
166166

167167
bb11: {
@@ -218,118 +218,89 @@
218218
+ }
219219
+
220220
+ bb21: {
221-
+ _1 = chained_conditions::BacktraceStyle::Off;
222-
+ goto -> bb40;
223-
+ }
224-
+
225-
+ bb22: {
226-
+ StorageDead(_5);
227-
+ StorageDead(_6);
228-
+ goto -> bb18;
229-
+ }
230-
+
231-
+ bb23: {
232-
+ StorageDead(_5);
233-
+ StorageDead(_6);
234-
+ goto -> bb25;
235-
+ }
236-
+
237-
+ bb24: {
238221
+ _24 = discriminant(_2);
239222
+ switchInt(move _24) -> [1: bb16, otherwise: bb15];
240223
+ }
241224
+
242-
+ bb25: {
225+
+ bb22: {
243226
+ _24 = discriminant(_2);
244-
+ switchInt(move _24) -> [1: bb28, otherwise: bb26];
227+
+ switchInt(move _24) -> [1: bb25, otherwise: bb23];
245228
+ }
246229
+
247-
+ bb26: {
230+
+ bb23: {
248231
+ _22 = const false;
249232
+ _23 = const false;
250233
+ StorageDead(_2);
251234
+ _19 = discriminant(_1);
252235
+ goto -> bb11;
253236
+ }
254237
+
255-
+ bb27: {
238+
+ bb24: {
256239
+ switchInt(copy _23) -> [0: bb15, otherwise: bb17];
257240
+ }
258241
+
259-
+ bb28: {
260-
+ goto -> bb26;
261-
+ }
262-
+
263-
+ bb29: {
264-
+ StorageDead(_12);
265-
+ StorageDead(_13);
266-
+ goto -> bb18;
267-
+ }
268-
+
269-
+ bb30: {
270-
+ StorageDead(_12);
271-
+ StorageDead(_13);
272-
+ goto -> bb32;
242+
+ bb25: {
243+
+ goto -> bb23;
273244
+ }
274245
+
275-
+ bb31: {
246+
+ bb26: {
276247
+ _24 = discriminant(_2);
277248
+ switchInt(move _24) -> [1: bb16, otherwise: bb15];
278249
+ }
279250
+
280-
+ bb32: {
251+
+ bb27: {
281252
+ _24 = discriminant(_2);
282-
+ switchInt(move _24) -> [1: bb35, otherwise: bb33];
253+
+ switchInt(move _24) -> [1: bb30, otherwise: bb28];
283254
+ }
284255
+
285-
+ bb33: {
256+
+ bb28: {
286257
+ _22 = const false;
287258
+ _23 = const false;
288259
+ StorageDead(_2);
289260
+ _19 = discriminant(_1);
290261
+ goto -> bb13;
291262
+ }
292263
+
293-
+ bb34: {
264+
+ bb29: {
294265
+ switchInt(copy _23) -> [0: bb15, otherwise: bb17];
295266
+ }
296267
+
297-
+ bb35: {
298-
+ goto -> bb33;
268+
+ bb30: {
269+
+ goto -> bb28;
299270
+ }
300271
+
301-
+ bb36: {
272+
+ bb31: {
302273
+ _24 = discriminant(_2);
303-
+ switchInt(move _24) -> [1: bb38, otherwise: bb37];
274+
+ switchInt(move _24) -> [1: bb33, otherwise: bb32];
304275
+ }
305276
+
306-
+ bb37: {
277+
+ bb32: {
307278
+ _22 = const false;
308279
+ _23 = const false;
309280
+ StorageDead(_2);
310281
+ _19 = discriminant(_1);
311282
+ goto -> bb12;
312283
+ }
313284
+
314-
+ bb38: {
315-
+ switchInt(copy _23) -> [0: bb37, otherwise: bb39];
285+
+ bb33: {
286+
+ switchInt(copy _23) -> [0: bb32, otherwise: bb34];
316287
+ }
317288
+
318-
+ bb39: {
319-
+ drop(((_2 as Some).0: std::string::String)) -> [return: bb37, unwind unreachable];
289+
+ bb34: {
290+
+ drop(((_2 as Some).0: std::string::String)) -> [return: bb32, unwind unreachable];
320291
+ }
321292
+
322-
+ bb40: {
293+
+ bb35: {
323294
+ _24 = discriminant(_2);
324-
+ switchInt(move _24) -> [1: bb41, otherwise: bb33];
295+
+ switchInt(move _24) -> [1: bb36, otherwise: bb28];
325296
+ }
326297
+
327-
+ bb41: {
328-
+ goto -> bb42;
298+
+ bb36: {
299+
+ goto -> bb37;
329300
+ }
330301
+
331-
+ bb42: {
332-
+ drop(((_2 as Some).0: std::string::String)) -> [return: bb33, unwind unreachable];
302+
+ bb37: {
303+
+ drop(((_2 as Some).0: std::string::String)) -> [return: bb28, unwind unreachable];
333304
}
334305
}
335306

0 commit comments

Comments
 (0)