Skip to content

Commit 3920e07

Browse files
committed
Make coverage counter IDs count up from 0, not 1
Operand types are now tracked explicitly, so there is no need to reserve ID 0 for the special always-zero counter. As part of the renumbering, this change fixes an off-by-one error in the way counters were counted by the `coverageinfo` query. As a result, functions should now have exactly the number of counters they actually need, instead of always having an extra counter that is never used.
1 parent f103db8 commit 3920e07

12 files changed

+43
-61
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
1+
use rustc_middle::mir::coverage::{CounterId, MappedExpressionIndex};
22

33
/// Must match the layout of `LLVMRustCounterKind`.
44
#[derive(Copy, Clone, Debug)]
@@ -36,11 +36,9 @@ impl Counter {
3636
Self { kind: CounterKind::Zero, id: 0 }
3737
}
3838

39-
/// Constructs a new `Counter` of kind `CounterValueReference`, and converts
40-
/// the given 1-based counter_id to the required 0-based equivalent for
41-
/// the `Counter` encoding.
42-
pub fn counter_value_reference(counter_id: CounterValueReference) -> Self {
43-
Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() }
39+
/// Constructs a new `Counter` of kind `CounterValueReference`.
40+
pub fn counter_value_reference(counter_id: CounterId) -> Self {
41+
Self { kind: CounterKind::CounterValueReference, id: counter_id.as_u32() }
4442
}
4543

4644
/// Constructs a new `Counter` of kind `Expression`.

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pub use super::ffi::*;
33
use rustc_index::{IndexSlice, IndexVec};
44
use rustc_middle::bug;
55
use rustc_middle::mir::coverage::{
6-
CodeRegion, CounterValueReference, ExpressionId, MappedExpressionIndex, Op, Operand,
6+
CodeRegion, CounterId, ExpressionId, MappedExpressionIndex, Op, Operand,
77
};
88
use rustc_middle::ty::Instance;
99
use rustc_middle::ty::TyCtxt;
@@ -32,7 +32,7 @@ pub struct FunctionCoverage<'tcx> {
3232
instance: Instance<'tcx>,
3333
source_hash: u64,
3434
is_used: bool,
35-
counters: IndexVec<CounterValueReference, Option<CodeRegion>>,
35+
counters: IndexVec<CounterId, Option<CodeRegion>>,
3636
expressions: IndexVec<ExpressionId, Option<Expression>>,
3737
unreachable_regions: Vec<CodeRegion>,
3838
}
@@ -80,7 +80,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
8080
}
8181

8282
/// Adds a code region to be counted by an injected counter intrinsic.
83-
pub fn add_counter(&mut self, id: CounterValueReference, region: CodeRegion) {
83+
pub fn add_counter(&mut self, id: CounterId, region: CodeRegion) {
8484
if let Some(previous_region) = self.counters[id].replace(region.clone()) {
8585
assert_eq!(previous_region, region, "add_counter: code region for id changed");
8686
}
@@ -192,18 +192,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
192192
type NewIndexes = IndexSlice<ExpressionId, Option<MappedExpressionIndex>>;
193193
let id_to_counter = |new_indexes: &NewIndexes, operand: Operand| match operand {
194194
Operand::Zero => Some(Counter::zero()),
195-
Operand::Counter(id) => {
196-
debug_assert!(
197-
id.index() > 0,
198-
"Operand::Counter indexes for counters are 1-based, but this id={}",
199-
id.index()
200-
);
201-
// Note: Some codegen-injected Counters may be only referenced by `Expression`s,
202-
// and may not have their own `CodeRegion`s,
203-
let index = CounterValueReference::from(id.index());
204-
// Note, the conversion to LLVM `Counter` adjusts the index to be zero-based.
205-
Some(Counter::counter_value_reference(index))
206-
}
195+
Operand::Counter(id) => Some(Counter::counter_value_reference(id)),
207196
Operand::Expression(id) => {
208197
self.expressions
209198
.get(id)

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ use rustc_hir as hir;
1616
use rustc_hir::def_id::DefId;
1717
use rustc_llvm::RustString;
1818
use rustc_middle::bug;
19-
use rustc_middle::mir::coverage::{
20-
CodeRegion, CounterValueReference, CoverageKind, ExpressionId, Op, Operand,
21-
};
19+
use rustc_middle::mir::coverage::{CodeRegion, CounterId, CoverageKind, ExpressionId, Op, Operand};
2220
use rustc_middle::mir::Coverage;
2321
use rustc_middle::ty;
2422
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
@@ -33,7 +31,7 @@ mod ffi;
3331
pub(crate) mod map_data;
3432
pub mod mapgen;
3533

36-
const UNUSED_FUNCTION_COUNTER_ID: CounterValueReference = CounterValueReference::START;
34+
const UNUSED_FUNCTION_COUNTER_ID: CounterId = CounterId::START;
3735

3836
const VAR_ALIGN_BYTES: usize = 8;
3937

@@ -125,7 +123,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
125123
let fn_name = bx.get_pgo_func_name_var(instance);
126124
let hash = bx.const_u64(function_source_hash);
127125
let num_counters = bx.const_u32(coverageinfo.num_counters);
128-
let index = bx.const_u32(id.zero_based_index());
126+
let index = bx.const_u32(id.as_u32());
129127
debug!(
130128
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
131129
fn_name, hash, num_counters, index,
@@ -178,7 +176,7 @@ impl<'tcx> Builder<'_, '_, 'tcx> {
178176
fn add_coverage_counter(
179177
&mut self,
180178
instance: Instance<'tcx>,
181-
id: CounterValueReference,
179+
id: CounterId,
182180
region: CodeRegion,
183181
) -> bool {
184182
if let Some(coverage_context) = self.coverage_context() {

compiler/rustc_middle/src/mir/coverage.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ use rustc_span::Symbol;
66
use std::fmt::{self, Debug, Formatter};
77

88
rustc_index::newtype_index! {
9+
/// ID of a coverage counter. Values ascend from 0.
10+
///
11+
/// Note that LLVM handles counter IDs as `uint32_t`, so there is no need
12+
/// to use a larger representation on the Rust side.
913
#[derive(HashStable)]
1014
#[max = 0xFFFF_FFFF]
11-
#[debug_format = "CounterValueReference({})"]
12-
pub struct CounterValueReference {}
15+
#[debug_format = "CounterId({})"]
16+
pub struct CounterId {}
1317
}
1418

15-
impl CounterValueReference {
16-
/// Counters start at 1 for historical reasons.
17-
pub const START: Self = Self::from_u32(1);
19+
impl CounterId {
20+
pub const START: Self = Self::from_u32(0);
1821

19-
/// Returns explicitly-requested zero-based version of the counter id, used
20-
/// during codegen. LLVM expects zero-based indexes.
21-
pub fn zero_based_index(self) -> u32 {
22-
let one_based_index = self.as_u32();
23-
debug_assert!(one_based_index > 0);
24-
one_based_index - 1
22+
#[inline(always)]
23+
pub fn next_id(self) -> Self {
24+
Self::from_u32(self.as_u32() + 1)
2525
}
2626
}
2727

@@ -63,7 +63,7 @@ rustc_index::newtype_index! {
6363
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
6464
pub enum Operand {
6565
Zero,
66-
Counter(CounterValueReference),
66+
Counter(CounterId),
6767
Expression(ExpressionId),
6868
}
6969

@@ -83,7 +83,7 @@ pub enum CoverageKind {
8383
function_source_hash: u64,
8484
/// ID of this counter within its enclosing function.
8585
/// Expressions in the same function can refer to it as an operand.
86-
id: CounterValueReference,
86+
id: CounterId,
8787
},
8888
Expression {
8989
/// ID of this coverage-counter expression within its enclosing function.

compiler/rustc_middle/src/ty/structural_impls.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ TrivialTypeTraversalAndLiftImpls! {
470470
::rustc_hir::Unsafety,
471471
::rustc_target::asm::InlineAsmRegOrRegClass,
472472
::rustc_target::spec::abi::Abi,
473-
crate::mir::coverage::CounterValueReference,
473+
crate::mir::coverage::CounterId,
474474
crate::mir::coverage::ExpressionId,
475475
crate::mir::coverage::MappedExpressionIndex,
476476
crate::mir::Local,

compiler/rustc_mir_transform/src/coverage/counters.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::mir::coverage::*;
1616
/// `Coverage` statements.
1717
pub(super) struct CoverageCounters {
1818
function_source_hash: u64,
19-
next_counter_id: u32,
19+
next_counter_id: CounterId,
2020
next_expression_id: ExpressionId,
2121
pub debug_counters: DebugCounters,
2222
}
@@ -25,7 +25,7 @@ impl CoverageCounters {
2525
pub fn new(function_source_hash: u64) -> Self {
2626
Self {
2727
function_source_hash,
28-
next_counter_id: CounterValueReference::START.as_u32(),
28+
next_counter_id: CounterId::START,
2929
next_expression_id: ExpressionId::START,
3030
debug_counters: DebugCounters::new(),
3131
}
@@ -93,10 +93,10 @@ impl CoverageCounters {
9393
}
9494

9595
/// Counter IDs start from one and go up.
96-
fn next_counter(&mut self) -> CounterValueReference {
96+
fn next_counter(&mut self) -> CounterId {
9797
let next = self.next_counter_id;
98-
self.next_counter_id += 1;
99-
CounterValueReference::from(next)
98+
self.next_counter_id = next.next_id();
99+
next
100100
}
101101

102102
/// Expression IDs start from 0 and go up.

compiler/rustc_mir_transform/src/coverage/query.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ struct CoverageVisitor {
4343
}
4444

4545
impl CoverageVisitor {
46-
/// Updates `num_counters` to the maximum encountered zero-based counter_id plus 1. Note the
47-
/// final computed number of counters should be the number of all `CoverageKind::Counter`
48-
/// statements in the MIR *plus one* for the implicit `ZERO` counter.
46+
/// Updates `num_counters` to the maximum encountered counter ID plus 1.
4947
#[inline(always)]
50-
fn update_num_counters(&mut self, counter_id: CounterValueReference) {
48+
fn update_num_counters(&mut self, counter_id: CounterId) {
5149
let counter_id = counter_id.as_u32();
5250
self.info.num_counters = std::cmp::max(self.info.num_counters, counter_id + 1);
5351
}
@@ -103,8 +101,7 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
103101
let mir_body = tcx.instance_mir(instance_def);
104102

105103
let mut coverage_visitor = CoverageVisitor {
106-
// num_counters always has at least the `ZERO` counter.
107-
info: CoverageInfo { num_counters: 1, num_expressions: 0 },
104+
info: CoverageInfo { num_counters: 0, num_expressions: 0 },
108105
add_missing_operands: false,
109106
};
110107

compiler/rustc_mir_transform/src/coverage/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,7 @@ fn test_make_bcb_counters() {
683683

684684
let_bcb!(1);
685685
assert_eq!(
686-
1, // coincidentally, bcb1 has a `Counter` with id = 1
686+
0, // bcb1 has a `Counter` with id = 0
687687
match basic_coverage_blocks[bcb1].counter().expect("should have a counter") {
688688
CoverageKind::Counter { id, .. } => id,
689689
_ => panic!("expected a Counter"),
@@ -693,7 +693,7 @@ fn test_make_bcb_counters() {
693693

694694
let_bcb!(2);
695695
assert_eq!(
696-
2, // coincidentally, bcb2 has a `Counter` with id = 2
696+
1, // bcb2 has a `Counter` with id = 1
697697
match basic_coverage_blocks[bcb2].counter().expect("should have a counter") {
698698
CoverageKind::Counter { id, .. } => id,
699699
_ => panic!("expected a Counter"),

tests/mir-opt/coverage_graphviz.bar.InstrumentCoverage.0.dot

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ digraph Cov_0_4 {
22
graph [fontname="Courier, monospace"];
33
node [fontname="Courier, monospace"];
44
edge [fontname="Courier, monospace"];
5-
bcb0__Cov_0_4 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 18:1-20:2<br align="left"/> 19:5-19:9: @0[0]: Coverage::Counter(1) for $DIR/coverage_graphviz.rs:18:1 - 20:2<br align="left"/> 20:2-20:2: @0.Return: return</td></tr><tr><td align="left" balign="left">bb0: Return</td></tr></table>>];
5+
bcb0__Cov_0_4 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 18:1-20:2<br align="left"/> 19:5-19:9: @0[0]: Coverage::Counter(0) for $DIR/coverage_graphviz.rs:18:1 - 20:2<br align="left"/> 20:2-20:2: @0.Return: return</td></tr><tr><td align="left" balign="left">bb0: Return</td></tr></table>>];
66
}

tests/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ digraph Cov_0_3 {
22
graph [fontname="Courier, monospace"];
33
node [fontname="Courier, monospace"];
44
edge [fontname="Courier, monospace"];
5-
bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br align="left"/> 13:10-13:10: @5[0]: Coverage::Counter(2) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>];
5+
bcb3__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb3</td></tr><tr><td align="left" balign="left">Counter(bcb3) at 13:10-13:10<br align="left"/> 13:10-13:10: @5[0]: Coverage::Counter(1) for $DIR/coverage_graphviz.rs:13:10 - 13:11</td></tr><tr><td align="left" balign="left">bb5: Goto</td></tr></table>>];
66
bcb2__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb2</td></tr><tr><td align="left" balign="left">Expression(bcb1:(bcb0 + bcb3) - bcb3) at 12:13-12:18<br align="left"/> 12:13-12:18: @4[0]: Coverage::Expression(2) = Expression(1) + Zero for $DIR/coverage_graphviz.rs:15:1 - 15:2<br align="left"/>Expression(bcb2:(bcb1:(bcb0 + bcb3) - bcb3) + 0) at 15:2-15:2<br align="left"/> 15:2-15:2: @4.Return: return</td></tr><tr><td align="left" balign="left">bb4: Return</td></tr></table>>];
77
bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br align="left"/> 11:12-11:17: @2.Call: _2 = bar() -&gt; [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br align="left"/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
88
bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br align="left"/> </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];

tests/mir-opt/instrument_coverage.bar.InstrumentCoverage.diff

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
let mut _0: bool;
66

77
bb0: {
8-
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:20:1 - 22:2;
8+
+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:20:1 - 22:2;
99
_0 = const true;
1010
return;
1111
}

tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
let mut _3: !;
99

1010
bb0: {
11-
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:11:1 - 11:11;
11+
+ Coverage::Counter(0) for /the/src/instrument_coverage.rs:11:1 - 11:11;
1212
goto -> bb1;
1313
}
1414

1515
bb1: {
16-
+ Coverage::Expression(0) = Counter(1) + Counter(2) for /the/src/instrument_coverage.rs:12:5 - 13:17;
16+
+ Coverage::Expression(0) = Counter(0) + Counter(1) for /the/src/instrument_coverage.rs:12:5 - 13:17;
1717
falseUnwind -> [real: bb2, unwind: bb6];
1818
}
1919

@@ -28,14 +28,14 @@
2828

2929
bb4: {
3030
+ Coverage::Expression(2) = Expression(1) + Zero for /the/src/instrument_coverage.rs:17:1 - 17:2;
31-
+ Coverage::Expression(1) = Expression(0) - Counter(2) for /the/src/instrument_coverage.rs:14:13 - 14:18;
31+
+ Coverage::Expression(1) = Expression(0) - Counter(1) for /the/src/instrument_coverage.rs:14:13 - 14:18;
3232
_0 = const ();
3333
StorageDead(_2);
3434
return;
3535
}
3636

3737
bb5: {
38-
+ Coverage::Counter(2) for /the/src/instrument_coverage.rs:15:10 - 15:11;
38+
+ Coverage::Counter(1) for /the/src/instrument_coverage.rs:15:10 - 15:11;
3939
_1 = const ();
4040
StorageDead(_2);
4141
goto -> bb1;

0 commit comments

Comments
 (0)