diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 53ff67f60e37..b7ddd52e9ac1 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -386,6 +386,24 @@ pub fn dominates(&self, a: Node, b: Node) -> bool { } } } + + /// Returns true if `a` **strictly** dominates `b` + /// + /// # Panics + /// + /// Panics if `b` is unreachable + #[inline] + pub fn strictly_dominates(&self, a: Node, b: Node) -> bool { + match &self.kind { + Kind::Path => a.index() < b.index(), + Kind::General(g) => { + let a = g.time[a]; + let b = g.time[b]; + assert!(b.start != 0, "node {b:?} is not reachable"); + a.start < b.start && b.finish < a.finish + } + } + } } /// Describes the number of vertices discovered at the time when processing of a particular vertex diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 36752bba9f72..d5795e64089b 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1609,6 +1609,11 @@ pub fn dominates(&self, other: Location, dominators: &Dominators) -> dominators.dominates(self.block, other.block) } } + + #[inline] + pub fn strictly_dominates(&self, other: Location, dominators: &Dominators) -> bool { + self.block != other.block && dominators.strictly_dominates(self.block, other.block) + } } /// `DefLocation` represents the location of a definition - either an argument or an assignment diff --git a/compiler/rustc_mir_transform/src/ssa_range_prop.rs b/compiler/rustc_mir_transform/src/ssa_range_prop.rs index 97ba07d90096..cd73471f20eb 100644 --- a/compiler/rustc_mir_transform/src/ssa_range_prop.rs +++ b/compiler/rustc_mir_transform/src/ssa_range_prop.rs @@ -163,8 +163,7 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Loca && self.is_ssa(place) => { let successor = Location { block: *target, statement_index: 0 }; - if location.dominates(successor, &self.dominators) { - assert_ne!(location.block, successor.block); + if location.strictly_dominates(successor, &self.dominators) { let val = *expected as u128; let range = WrappingRange { start: val, end: val }; self.insert_range(place, successor, range); diff --git a/tests/ui/mir/ssa-range-prop-bb-self-domination.rs b/tests/ui/mir/ssa-range-prop-bb-self-domination.rs new file mode 100644 index 000000000000..3f6249adc37e --- /dev/null +++ b/tests/ui/mir/ssa-range-prop-bb-self-domination.rs @@ -0,0 +1,22 @@ +/// Regression test for . +/// +/// SsaRangeProp pass used to fail the assert when encountering self-dominating block +/// e.g. small loops like in `a` + +//@ compile-flags: -Copt-level=2 +//@ build-pass + +use std::hint::black_box; +fn a(d: u8) { + loop { + 1 % d; + } +} +pub fn e(d: u8) { + if d == 0 || black_box(false) { + a(d); + } +} +fn main() { + e(1); +}