@@ -35,6 +35,11 @@ const ID_SEPARATOR: &str = ",";
3535
3636const 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 ) ]
3944struct 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-
10401040struct 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