Skip to content

Commit d6e65f9

Browse files
committed
Auto merge of rust-lang#147803 - jsgf:move-copy-codegen, r=madsmtm,saethlin
Add -Zannotate-moves for profiler visibility of move/copy operations (codegen) **Note:** this is an alternative implementation of rust-lang#147206; rather than being a MIR transform, it adds the annotations closer to codegen. It's functionally the same but the implementation is lower impact and it could be more correct. --- This implements a new unstable compiler flag `-Zannotate-moves` that makes move and copy operations visible in profilers by creating synthetic debug information. This is achieved with zero runtime cost by manipulating debug info scopes to make moves/copies appear as calls to `compiler_move<T, SIZE>` and `compiler_copy<T, SIZE>` marker functions in profiling tools. This allows developers to identify expensive move/copy operations in their code using standard profiling tools, without requiring specialized tooling or runtime instrumentation. The implementation works at codegen time. When processing MIR operands (`Operand::Move` and `Operand::Copy`), the codegen creates an `OperandRef` with an optional `move_annotation` field containing an `Instance` of the appropriate profiling marker function. When storing the operand, `store_with_annotation()` wraps the store operation in a synthetic debug scope that makes it appear inlined from the marker. Two marker functions (`compiler_move` and `compiler_copy`) are defined in `library/core/src/profiling.rs`. These are never actually called - they exist solely as debug info anchors. Operations are only annotated if: - We're generating debug info and the feature is enabled. - Meets the size threshold (default: 65 bytes, configurable via `-Zannotate-moves=SIZE`), and is non-zero - Has a memory representation This has a very small size impact on object file size. With the default limit it's well under 0.1%, and even with a very small limit of 8 bytes it's still ~1.5%. This could be enabled by default.
2 parents 99763e3 + a33fc72 commit d6e65f9

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ pub mod num;
282282
pub mod hint;
283283
pub mod intrinsics;
284284
pub mod mem;
285+
#[unstable(feature = "profiling_marker_api", issue = "148197")]
286+
pub mod profiling;
285287
pub mod ptr;
286288
#[unstable(feature = "ub_checks", issue = "none")]
287289
pub mod ub_checks;

core/src/profiling.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Profiling markers for compiler instrumentation.
2+
3+
/// Profiling marker for move operations.
4+
///
5+
/// This function is never called at runtime. When `-Z annotate-moves` is enabled,
6+
/// the compiler creates synthetic debug info that makes move operations appear as
7+
/// calls to this function in profilers.
8+
///
9+
/// The `SIZE` parameter encodes the size of the type being copied. It's the same as
10+
/// `size_of::<T>()`, and is only present for convenience.
11+
#[unstable(feature = "profiling_marker_api", issue = "148197")]
12+
#[lang = "compiler_move"]
13+
pub fn compiler_move<T, const SIZE: usize>(_src: *const T, _dst: *mut T) {
14+
unreachable!(
15+
"compiler_move marks where the compiler-generated a memcpy for moves. It is never actually called."
16+
)
17+
}
18+
19+
/// Profiling marker for copy operations.
20+
///
21+
/// This function is never called at runtime. When `-Z annotate-moves` is enabled,
22+
/// the compiler creates synthetic debug info that makes copy operations appear as
23+
/// calls to this function in profilers.
24+
///
25+
/// The `SIZE` parameter encodes the size of the type being copied. It's the same as
26+
/// `size_of::<T>()`, and is only present for convenience.
27+
#[unstable(feature = "profiling_marker_api", issue = "148197")]
28+
#[lang = "compiler_copy"]
29+
pub fn compiler_copy<T, const SIZE: usize>(_src: *const T, _dst: *mut T) {
30+
unreachable!(
31+
"compiler_copy marks where the compiler-generated a memcpy for Copies. It is never actually called."
32+
)
33+
}

0 commit comments

Comments
 (0)