Skip to content

Commit cc00eb0

Browse files
committed
Don't automatically add counters to BCBs without CoverageSpans
They may still get counters but only if there are dependencies from other BCBs that have spans, I think. At least one test, "various_conditions.rs", seems to have simplified counters as a result of this change, for whatever reason.
1 parent 756b920 commit cc00eb0

File tree

3 files changed

+236
-230
lines changed

3 files changed

+236
-230
lines changed

compiler/rustc_mir/src/transform/instrument_coverage.rs

Lines changed: 136 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ const ID_SEPARATOR: &str = ",";
3535

3636
const RUSTC_COVERAGE_DEBUG_OPTIONS: &str = "RUSTC_COVERAGE_DEBUG_OPTIONS";
3737

38+
/// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
39+
/// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
40+
/// to construct the coverage map.
41+
pub struct InstrumentCoverage;
42+
3843
#[derive(Debug, Clone)]
3944
struct DebugOptions {
4045
allow_unused_expressions: bool,
@@ -138,10 +143,119 @@ impl Default for ExpressionFormat {
138143
}
139144
}
140145

141-
/// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
142-
/// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
143-
/// to construct the coverage map.
144-
pub struct InstrumentCoverage;
146+
#[derive(Debug)]
147+
struct DebugCounter {
148+
counter_kind: CoverageKind,
149+
some_block_label: Option<String>,
150+
}
151+
152+
impl DebugCounter {
153+
fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self {
154+
Self {
155+
counter_kind,
156+
some_block_label,
157+
}
158+
}
159+
}
160+
161+
struct DebugCounters {
162+
some_counters: Option<FxHashMap<ExpressionOperandId, DebugCounter>>,
163+
}
164+
165+
impl DebugCounters {
166+
pub fn new() -> Self {
167+
Self {
168+
some_counters: None,
169+
}
170+
}
171+
172+
pub fn enable(&mut self) {
173+
self.some_counters.replace(FxHashMap::default());
174+
}
175+
176+
pub fn is_enabled(&mut self) -> bool {
177+
self.some_counters.is_some()
178+
}
179+
180+
pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) {
181+
if let Some(counters) = &mut self.some_counters {
182+
let id: ExpressionOperandId = match *counter_kind {
183+
CoverageKind::Counter { id, .. } => id.into(),
184+
| CoverageKind::Expression { id, .. } => id.into(),
185+
_ => bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind),
186+
};
187+
counters.insert(id.into(), DebugCounter::new(counter_kind.clone(), some_block_label)).expect_none("attempt to add the same counter_kind to DebugCounters more than once");
188+
}
189+
}
190+
191+
pub fn some_block_label(&self, operand: ExpressionOperandId) -> Option<&String> {
192+
self.some_counters.as_ref().map_or(None, |counters| counters.get(&operand).map_or(None, |debug_counter| debug_counter.some_block_label.as_ref()))
193+
}
194+
195+
pub fn format_counter(&self, counter_kind: &CoverageKind) -> String {
196+
match *counter_kind {
197+
CoverageKind::Counter { .. } => format!("Counter({})", self.format_counter_kind(counter_kind)),
198+
CoverageKind::Expression { .. } => format!("Expression({})", self.format_counter_kind(counter_kind)),
199+
CoverageKind::Unreachable { .. } => "Unreachable".to_owned(),
200+
}
201+
}
202+
203+
fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String {
204+
let counter_format = &debug_options().counter_format;
205+
if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind {
206+
if counter_format.operation {
207+
return format!(
208+
"{}{} {} {}",
209+
if counter_format.id || self.some_counters.is_none() {
210+
format!("#{} = ", id.index() )
211+
} else {
212+
String::new()
213+
},
214+
self.format_operand(lhs),
215+
if op == Op::Add { "+" } else { "-" },
216+
self.format_operand(rhs),
217+
);
218+
}
219+
}
220+
221+
let id: ExpressionOperandId = match *counter_kind {
222+
CoverageKind::Counter { id, .. } => id.into(),
223+
| CoverageKind::Expression { id, .. } => id.into(),
224+
_ => bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind),
225+
};
226+
if self.some_counters.is_some() && (counter_format.block || !counter_format.id) {
227+
let counters = self.some_counters.as_ref().unwrap();
228+
if let Some(DebugCounter { some_block_label: Some(block_label), .. }) = counters.get(&id.into()) {
229+
return if counter_format.id {
230+
format!("{}#{}", block_label, id.index())
231+
} else {
232+
format!("{}", block_label)
233+
}
234+
}
235+
}
236+
format!("#{}", id.index())
237+
}
238+
239+
fn format_operand(&self, operand: ExpressionOperandId) -> String {
240+
if operand.index() == 0 {
241+
return String::from("0");
242+
}
243+
if let Some(counters) = &self.some_counters {
244+
if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
245+
if let CoverageKind::Expression { .. } = counter_kind {
246+
if let Some(block_label) = some_block_label {
247+
if debug_options().counter_format.block {
248+
return format!("{}:({})", block_label, self.format_counter_kind(counter_kind));
249+
}
250+
}
251+
return format!("({})", self.format_counter_kind(counter_kind));
252+
}
253+
return format!("{}", self.format_counter_kind(counter_kind));
254+
}
255+
}
256+
format!("#{}", operand.index().to_string())
257+
}
258+
}
145259

146260
/// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each
147261
/// counter) and `FunctionCoverage::new()` (to extract the coverage map metadata from the MIR).
@@ -923,120 +1037,6 @@ struct TraversalContext {
9231037
worklist: Vec<BasicCoverageBlock>,
9241038
}
9251039

926-
#[derive(Debug)]
927-
struct DebugCounter {
928-
counter_kind: CoverageKind,
929-
some_block_label: Option<String>,
930-
}
931-
932-
impl DebugCounter {
933-
fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self {
934-
Self {
935-
counter_kind,
936-
some_block_label,
937-
}
938-
}
939-
}
940-
941-
struct DebugCounters {
942-
some_counters: Option<FxHashMap<ExpressionOperandId, DebugCounter>>,
943-
}
944-
945-
impl DebugCounters {
946-
pub fn new() -> Self {
947-
Self {
948-
some_counters: None,
949-
}
950-
}
951-
952-
pub fn enable(&mut self) {
953-
self.some_counters.replace(FxHashMap::default());
954-
}
955-
956-
pub fn is_enabled(&mut self) -> bool {
957-
self.some_counters.is_some()
958-
}
959-
960-
pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) {
961-
if let Some(counters) = &mut self.some_counters {
962-
let id: ExpressionOperandId = match *counter_kind {
963-
CoverageKind::Counter { id, .. } => id.into(),
964-
| CoverageKind::Expression { id, .. } => id.into(),
965-
_ => bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind),
966-
};
967-
counters.insert(id.into(), DebugCounter::new(counter_kind.clone(), some_block_label)).expect_none("attempt to add the same counter_kind to DebugCounters more than once");
968-
}
969-
}
970-
971-
pub fn some_block_label(&self, operand: ExpressionOperandId) -> Option<&String> {
972-
self.some_counters.as_ref().map_or(None, |counters| counters.get(&operand).map_or(None, |debug_counter| debug_counter.some_block_label.as_ref()))
973-
}
974-
975-
pub fn format_counter(&self, counter_kind: &CoverageKind) -> String {
976-
match *counter_kind {
977-
CoverageKind::Counter { .. } => format!("Counter({})", self.format_counter_kind(counter_kind)),
978-
CoverageKind::Expression { .. } => format!("Expression({})", self.format_counter_kind(counter_kind)),
979-
CoverageKind::Unreachable { .. } => "Unreachable".to_owned(),
980-
}
981-
}
982-
983-
fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String {
984-
let counter_format = &debug_options().counter_format;
985-
if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind {
986-
if counter_format.operation {
987-
return format!(
988-
"{}{} {} {}",
989-
if counter_format.id || self.some_counters.is_none() {
990-
format!("#{} = ", id.index() )
991-
} else {
992-
String::new()
993-
},
994-
self.format_operand(lhs),
995-
if op == Op::Add { "+" } else { "-" },
996-
self.format_operand(rhs),
997-
);
998-
}
999-
}
1000-
1001-
let id: ExpressionOperandId = match *counter_kind {
1002-
CoverageKind::Counter { id, .. } => id.into(),
1003-
| CoverageKind::Expression { id, .. } => id.into(),
1004-
_ => bug!("the given `CoverageKind` is not an counter or expression: {:?}", counter_kind),
1005-
};
1006-
if self.some_counters.is_some() && (counter_format.block || !counter_format.id) {
1007-
let counters = self.some_counters.as_ref().unwrap();
1008-
if let Some(DebugCounter { some_block_label: Some(block_label), .. }) = counters.get(&id.into()) {
1009-
return if counter_format.id {
1010-
format!("{}#{}", block_label, id.index())
1011-
} else {
1012-
format!("{}", block_label)
1013-
}
1014-
}
1015-
}
1016-
format!("#{}", id.index())
1017-
}
1018-
1019-
fn format_operand(&self, operand: ExpressionOperandId) -> String {
1020-
if operand.index() == 0 {
1021-
return String::from("0");
1022-
}
1023-
if let Some(counters) = &self.some_counters {
1024-
if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
1025-
if let CoverageKind::Expression { .. } = counter_kind {
1026-
if let Some(block_label) = some_block_label {
1027-
if debug_options().counter_format.block {
1028-
return format!("{}:({})", block_label, self.format_counter_kind(counter_kind));
1029-
}
1030-
}
1031-
return format!("({})", self.format_counter_kind(counter_kind));
1032-
}
1033-
return format!("{}", self.format_counter_kind(counter_kind));
1034-
}
1035-
}
1036-
format!("#{}", operand.index().to_string())
1037-
}
1038-
}
1039-
10401040
struct Instrumentor<'a, 'tcx> {
10411041
pass_name: &'a str,
10421042
tcx: TyCtxt<'tcx>,
@@ -1130,13 +1130,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
11301130
if level_enabled!(tracing::Level::DEBUG) || dump_graphviz {
11311131
debug_used_expression_operands = Some(FxHashMap::default());
11321132
debug_unused_expressions = Some(Vec::new());
1133-
// TODO(richkadel): remove me:
1134-
// const SIMPLIFY_EXPRESSIONS: bool = false;
1135-
// if SIMPLIFY_EXPRESSIONS {
11361133
if debug_options().simplify_expressions {
11371134
self.debug_expressions_cache.replace(FxHashMap::default());
11381135
}
1139-
// CAUTION! The `SIMPLIFY_EXPRESSIONS` option is only helpful for some debugging
1136+
// CAUTION! The `simplify_expressions` option is only helpful for some debugging
11401137
// situations and it can change the generated MIR `Coverage` statements (resulting in
11411138
// differences in behavior when enabled, under `DEBUG`, compared to normal operation and
11421139
// testing).
@@ -1165,10 +1162,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
11651162
debug_edge_to_counter = Some(FxHashMap::default());
11661163
}
11671164

1165+
let mut bcbs_with_coverage = BitSet::new_empty(self.basic_coverage_blocks.num_nodes());
1166+
for covspan in &coverage_spans {
1167+
bcbs_with_coverage.insert(covspan.bcb);
1168+
}
1169+
11681170
// Analyze the coverage graph (aka, BCB control flow graph), and inject expression-optimized
11691171
// counters.
1170-
1171-
self.make_bcb_counters(&mut collect_intermediate_expressions);
1172+
self.make_bcb_counters(bcbs_with_coverage, &mut collect_intermediate_expressions);
11721173

11731174
// If debugging, add any intermediate expressions (which are not associated with any BCB) to
11741175
// the `debug_used_expression_operands` map.
@@ -1438,14 +1439,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
14381439
// FIXME(richkadel): Determine if unused expressions can and should be prevented, and
14391440
// if so, it would be a `bug!` if encountered in the future. At the present time,
14401441
// however we do sometimes encounter unused expressions (in only a subset of test cases)
1441-
// even when `SIMPLIFY_EXPRESSIONS` is disabled. It's not yet clear what causes this, or
1442+
// even when `simplify_expressions` is disabled. It's not yet clear what causes this, or
14421443
// if it should be allowed in the long term, but as long as the coverage capability
14431444
// still works, generate warning messages only, for now.
1444-
// TODO(richkadel): remove:
1445-
// const ALLOW_UNUSED_EXPRESSIONS: bool = true;
1446-
// if self.debug_expressions_cache.is_some() || ALLOW_UNUSED_EXPRESSIONS {
14471445
if self.debug_expressions_cache.is_some() || debug_options().allow_unused_expressions {
1448-
// Note, the debugging const `SIMPLIFY_EXPRESSIONS`, which initializes the
1446+
// Note, the debugging option `simplify_expressions`, which initializes the
14491447
// `debug_expressions_cache` can cause some counters to become unused, and
14501448
// is not a bug.
14511449
//
@@ -1518,7 +1516,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
15181516
///
15191517
/// Returns non-code-span expressions created to represent intermediate values (if required),
15201518
/// such as to add two counters so the result can be subtracted from another counter.
1521-
fn make_bcb_counters(&mut self, collect_intermediate_expressions: &mut Vec<CoverageKind>) {
1519+
fn make_bcb_counters(
1520+
&mut self,
1521+
bcbs_with_coverage: BitSet<BasicCoverageBlock>,
1522+
collect_intermediate_expressions: &mut Vec<CoverageKind>,
1523+
) {
15221524
debug!("make_bcb_counters(): adding a counter or expression to each BasicCoverageBlock");
15231525
let num_bcbs = self.basic_coverage_blocks.num_nodes();
15241526
let mut backedges = IndexVec::from_elem_n(
@@ -1608,6 +1610,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
16081610
}
16091611
}
16101612

1613+
if !bcbs_with_coverage.contains(bcb) {
1614+
continue;
1615+
}
1616+
16111617
let bcb_counter_operand = self.get_or_make_counter_operand(bcb, collect_intermediate_expressions);
16121618

16131619
let needs_branch_counters = {

0 commit comments

Comments
 (0)