Skip to content

Commit c8dff28

Browse files
committed
Auto merge of #130456 - matthiaskrgr:rollup-h2qvk1f, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #130380 (coverage: Clarify some parts of coverage counter creation) - #130427 (run_make_support: rectify symlink handling) - #130447 (rustc_llvm: update for llvm/llvm-project@2ae968a0d9fb61606b020e898d88…) - #130448 (fix: Remove duplicate `LazyLock` example.) r? `@ghost` `@rustbot` modify labels: rollup
2 parents e2dc1a1 + 558b302 commit c8dff28

File tree

10 files changed

+334
-235
lines changed

10 files changed

+334
-235
lines changed

compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include "llvm/Target/TargetMachine.h"
2626
#include "llvm/Target/TargetOptions.h"
2727
#include "llvm/Transforms/IPO.h"
28-
#include "llvm/Transforms/Instrumentation.h"
2928
#include "llvm/Transforms/Scalar.h"
3029

3130
#define LLVM_VERSION_GE(major, minor) \
@@ -34,6 +33,12 @@
3433

3534
#define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor)))
3635

36+
#if LLVM_VERSION_GE(20, 0)
37+
#include "llvm/Transforms/Utils/Instrumentation.h"
38+
#else
39+
#include "llvm/Transforms/Instrumentation.h"
40+
#endif
41+
3742
#include "llvm/IR/LegacyPassManager.h"
3843

3944
#include "llvm/Bitcode/BitcodeReader.h"

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
#include "llvm/TargetParser/Host.h"
4040
#endif
4141
#include "llvm/Support/TimeProfiler.h"
42-
#include "llvm/Transforms/Instrumentation.h"
4342
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
4443
#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
4544
#if LLVM_VERSION_GE(19, 0)

compiler/rustc_mir_transform/src/coverage/counters.rs

+109-122
Large diffs are not rendered by default.

compiler/rustc_mir_transform/src/coverage/graph.rs

+61-29
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ impl CoverageGraph {
8787
for &bb in basic_blocks.iter() {
8888
bb_to_bcb[bb] = Some(bcb);
8989
}
90-
let bcb_data = BasicCoverageBlockData::from(basic_blocks);
90+
91+
let is_out_summable = basic_blocks.last().map_or(false, |&bb| {
92+
bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable()
93+
});
94+
let bcb_data = BasicCoverageBlockData { basic_blocks, is_out_summable };
9195
debug!("adding bcb{}: {:?}", bcb.index(), bcb_data);
9296
bcbs.push(bcb_data);
9397
};
@@ -161,23 +165,33 @@ impl CoverageGraph {
161165
self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
162166
}
163167

164-
/// Returns true if the given node has 2 or more in-edges, i.e. 2 or more
165-
/// predecessors.
166-
///
167-
/// This property is interesting to code that assigns counters to nodes and
168-
/// edges, because if a node _doesn't_ have multiple in-edges, then there's
169-
/// no benefit in having a separate counter for its in-edge, because it
170-
/// would have the same value as the node's own counter.
171-
///
172-
/// FIXME: That assumption might not be true for [`TerminatorKind::Yield`]?
173-
#[inline(always)]
174-
pub(crate) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
175-
// Even though bcb0 conceptually has an extra virtual in-edge due to
176-
// being the entry point, we've already asserted that it has no _other_
177-
// in-edges, so there's no possibility of it having _multiple_ in-edges.
178-
// (And since its virtual in-edge doesn't exist in the graph, that edge
179-
// can't have a separate counter anyway.)
180-
self.predecessors[bcb].len() > 1
168+
/// Returns the source of this node's sole in-edge, if it has exactly one.
169+
/// That edge can be assumed to have the same execution count as the node
170+
/// itself (in the absence of panics).
171+
pub(crate) fn sole_predecessor(
172+
&self,
173+
to_bcb: BasicCoverageBlock,
174+
) -> Option<BasicCoverageBlock> {
175+
// Unlike `simple_successor`, there is no need for extra checks here.
176+
if let &[from_bcb] = self.predecessors[to_bcb].as_slice() { Some(from_bcb) } else { None }
177+
}
178+
179+
/// Returns the target of this node's sole out-edge, if it has exactly
180+
/// one, but only if that edge can be assumed to have the same execution
181+
/// count as the node itself (in the absence of panics).
182+
pub(crate) fn simple_successor(
183+
&self,
184+
from_bcb: BasicCoverageBlock,
185+
) -> Option<BasicCoverageBlock> {
186+
// If a node's count is the sum of its out-edges, and it has exactly
187+
// one out-edge, then that edge has the same count as the node.
188+
if self.bcbs[from_bcb].is_out_summable
189+
&& let &[to_bcb] = self.successors[from_bcb].as_slice()
190+
{
191+
Some(to_bcb)
192+
} else {
193+
None
194+
}
181195
}
182196
}
183197

@@ -266,14 +280,16 @@ rustc_index::newtype_index! {
266280
#[derive(Debug, Clone)]
267281
pub(crate) struct BasicCoverageBlockData {
268282
pub(crate) basic_blocks: Vec<BasicBlock>,
283+
284+
/// If true, this node's execution count can be assumed to be the sum of the
285+
/// execution counts of all of its **out-edges** (assuming no panics).
286+
///
287+
/// Notably, this is false for a node ending with [`TerminatorKind::Yield`],
288+
/// because the yielding coroutine might not be resumed.
289+
pub(crate) is_out_summable: bool,
269290
}
270291

271292
impl BasicCoverageBlockData {
272-
fn from(basic_blocks: Vec<BasicBlock>) -> Self {
273-
assert!(basic_blocks.len() > 0);
274-
Self { basic_blocks }
275-
}
276-
277293
#[inline(always)]
278294
pub(crate) fn leader_bb(&self) -> BasicBlock {
279295
self.basic_blocks[0]
@@ -295,13 +311,27 @@ enum CoverageSuccessors<'a> {
295311
Chainable(BasicBlock),
296312
/// The block cannot be combined into the same BCB as its successor(s).
297313
NotChainable(&'a [BasicBlock]),
314+
/// Yield terminators are not chainable, and their execution count can also
315+
/// differ from the execution count of their out-edge.
316+
Yield(BasicBlock),
298317
}
299318

300319
impl CoverageSuccessors<'_> {
301320
fn is_chainable(&self) -> bool {
302321
match self {
303322
Self::Chainable(_) => true,
304323
Self::NotChainable(_) => false,
324+
Self::Yield(_) => false,
325+
}
326+
}
327+
328+
/// Returns true if the terminator itself is assumed to have the same
329+
/// execution count as the sum of its out-edges (assuming no panics).
330+
fn is_out_summable(&self) -> bool {
331+
match self {
332+
Self::Chainable(_) => true,
333+
Self::NotChainable(_) => true,
334+
Self::Yield(_) => false,
305335
}
306336
}
307337
}
@@ -312,7 +342,9 @@ impl IntoIterator for CoverageSuccessors<'_> {
312342

313343
fn into_iter(self) -> Self::IntoIter {
314344
match self {
315-
Self::Chainable(bb) => Some(bb).into_iter().chain((&[]).iter().copied()),
345+
Self::Chainable(bb) | Self::Yield(bb) => {
346+
Some(bb).into_iter().chain((&[]).iter().copied())
347+
}
316348
Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()),
317349
}
318350
}
@@ -331,7 +363,7 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
331363

332364
// A yield terminator has exactly 1 successor, but should not be chained,
333365
// because its resume edge has a different execution count.
334-
Yield { ref resume, .. } => CoverageSuccessors::NotChainable(std::slice::from_ref(resume)),
366+
Yield { resume, .. } => CoverageSuccessors::Yield(resume),
335367

336368
// These terminators have exactly one coverage-relevant successor,
337369
// and can be chained into it.
@@ -341,15 +373,15 @@ fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> Covera
341373
| FalseUnwind { real_target: target, .. }
342374
| Goto { target } => CoverageSuccessors::Chainable(target),
343375

344-
// A call terminator can normally be chained, except when they have no
345-
// successor because they are known to diverge.
376+
// A call terminator can normally be chained, except when it has no
377+
// successor because it is known to diverge.
346378
Call { target: maybe_target, .. } => match maybe_target {
347379
Some(target) => CoverageSuccessors::Chainable(target),
348380
None => CoverageSuccessors::NotChainable(&[]),
349381
},
350382

351-
// An inline asm terminator can normally be chained, except when it diverges or uses asm
352-
// goto.
383+
// An inline asm terminator can normally be chained, except when it
384+
// diverges or uses asm goto.
353385
InlineAsm { ref targets, .. } => {
354386
if let [target] = targets[..] {
355387
CoverageSuccessors::Chainable(target)

library/std/src/sync/lazy_lock.rs

-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ union Data<T, F> {
4444
///
4545
/// // The `String` is built, stored in the `LazyLock`, and returned as `&String`.
4646
/// let _ = &*DEEP_THOUGHT;
47-
/// // The `String` is retrieved from the `LazyLock` and returned as `&String`.
48-
/// let _ = &*DEEP_THOUGHT;
4947
/// ```
5048
///
5149
/// Initialize fields with `LazyLock`.

0 commit comments

Comments
 (0)