From 54569c6fc70459916b3c894519c502d700436405 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 23 May 2026 16:58:04 -0400 Subject: [PATCH 1/6] Make hint::cold_path #[cold] so that it works even if the MIR inliner can't inline it --- library/core/src/hint.rs | 3 + .../hint/cold_path-target_feature.rs | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/codegen-llvm/hint/cold_path-target_feature.rs diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index a8e01e6e78b4b..90326e649058b 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -778,6 +778,9 @@ pub const fn unlikely(b: bool) -> bool { #[stable(feature = "cold_path", since = "1.95.0")] #[rustc_const_stable(feature = "cold_path", since = "1.95.0")] #[inline(always)] +// Even if for some reason the cold_path intrinsic is not visible to codegen, the coldness will +// ensure that branches this is in are still known to be cold. +#[cold] pub const fn cold_path() { crate::intrinsics::cold_path() } diff --git a/tests/codegen-llvm/hint/cold_path-target_feature.rs b/tests/codegen-llvm/hint/cold_path-target_feature.rs new file mode 100644 index 0000000000000..9e06fd0ceafa1 --- /dev/null +++ b/tests/codegen-llvm/hint/cold_path-target_feature.rs @@ -0,0 +1,56 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +#![crate_type = "lib"] + +// This test checks that hint::cold_path still works in #[target_feature] functions. + +use std::hint::cold_path; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +#[no_mangle] +#[target_feature(enable = "sse2")] +pub fn with_target_feature(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @with_target_feature( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} From bcf900133d46083076c92c435d6410241fac1381 Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Sun, 24 May 2026 19:52:36 +0200 Subject: [PATCH 2/6] feat: rename debug-info-for-profiling switch --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/options.rs | 4 ++-- ...debug_info_for_profiling.md => debuginfo_for_profiling.md} | 4 ++-- .../unstable-book/src/compiler-flags/profile_sample_use.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) rename src/doc/unstable-book/src/compiler-flags/{debug_info_for_profiling.md => debuginfo_for_profiling.md} (93%) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 7b22ac231df1c..40236f2896e34 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -180,7 +180,7 @@ impl ModuleConfig { ), pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None), pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None), - debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, + debug_info_for_profiling: sess.opts.unstable_opts.debuginfo_for_profiling, instrument_coverage: if_regular!(sess.instrument_coverage(), false), sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0837e7767605c..0498d835df5f5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -782,8 +782,8 @@ fn test_unstable_options_tracking_hash() { ); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); - tracked!(debug_info_for_profiling, true); tracked!(debug_info_type_line_numbers, true); + tracked!(debuginfo_for_profiling, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index aa9331ee8f659..bbccff73fb34e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2252,12 +2252,12 @@ options! { "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), - debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], - "emit discriminators and other data necessary for AutoFDO"), debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], "emit type and line information for additional data types (default: no)"), debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], "compress debug info sections (none, zlib, zstd, default: none)"), + debuginfo_for_profiling: bool = (false, parse_bool, [TRACKED], + "emit discriminators and other data necessary for AutoFDO"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), default_visibility: Option = (None, parse_opt_symbol_visibility, [TRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md similarity index 93% rename from src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md rename to src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md index ee72b6adf8e9f..d25cdcaeb7427 100644 --- a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md +++ b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md @@ -1,4 +1,4 @@ -# `debug-info-for-profiling` +# `debuginfo-for-profiling` --- @@ -22,7 +22,7 @@ external tool `create_llvm_prof` from [this repository] must be used. Given a Rust file `main.rs`, we can produce an optimized binary as follows: ```shell -rustc -O -Zdebug-info-for-profiling main.rs -o main +rustc -O -Zdebuginfo-for-profiling main.rs -o main perf record -b ./main create_llvm_prof --binary=main --out=code.prof rustc -O -Zprofile-sample-use=code.prof main.rs -o main2 diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md index 2dd1f6f8e1a3a..a9bcca3e1522a 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -4,7 +4,7 @@ `-Zprofile-sample-use=code.prof` directs `rustc` to use the profile `code.prof` as a source for Automatic Feedback Directed Optimization (AFDO). -See the documentation of [`-Zdebug-info-for-profiling`] for more information +See the documentation of [`-Zdebuginfo-for-profiling`] for more information on using AFDO. -[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html +[`-Zdebuginfo-for-profiling`]: debuginfo_for_profiling.html From fe17ed58e960f9fa2195590c4b25457f2b2d9e9b Mon Sep 17 00:00:00 2001 From: Alexander Zaitsev Date: Sun, 10 May 2026 22:06:26 +0200 Subject: [PATCH 3/6] feat: add tests for `debuginfo-for-profiling` - the test was ported from this commit: https://github.com/llvm/llvm-project/commit/300921157385c5f6e0884537510c3ce1f336cd8c --- .../assembly-llvm/debuginfo-for-profiling.rs | 56 +++++++++++++++++++ tests/codegen-llvm/debuginfo-for-profiling.rs | 45 +++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tests/assembly-llvm/debuginfo-for-profiling.rs create mode 100644 tests/codegen-llvm/debuginfo-for-profiling.rs diff --git a/tests/assembly-llvm/debuginfo-for-profiling.rs b/tests/assembly-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..6431142e7b621 --- /dev/null +++ b/tests/assembly-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,56 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below. +// Actual count depends on the target +// +// +//@ add-minicore +//@ revisions: DEFAULT-X86 DEFAULT-AARCH64 DEBUGINFO-X86 DEBUGINFO-AARCH64 +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEFAULT-X86] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [DEFAULT-X86] needs-llvm-components: x86 +//@ [DEFAULT-AARCH64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [DEFAULT-AARCH64] needs-llvm-components: aarch64 +//@ [DEBUGINFO-X86] compile-flags: -Zdebuginfo-for-profiling --target=x86_64-unknown-linux-gnu +//@ [DEBUGINFO-X86] needs-llvm-components: x86 +//@ [DEBUGINFO-AARCH64] compile-flags: -Zdebuginfo-for-profiling --target=aarch64-unknown-linux-gnu +//@ [DEBUGINFO-AARCH64] needs-llvm-components: aarch64 +// DEFAULT-X86-NOT: discriminator +// DEFAULT-AARCH64-NOT: discriminator +// DEBUGINFO-X86-COUNT-1: discriminator +// DEBUGINFO-AARCH64-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} diff --git a/tests/codegen-llvm/debuginfo-for-profiling.rs b/tests/codegen-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..f7e401415ac7e --- /dev/null +++ b/tests/codegen-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,45 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below +// +// +//@ add-minicore +//@ revisions: DEFAULT DEBUGINFO +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEBUGINFO] compile-flags: -Zdebuginfo-for-profiling +// DEFAULT-NOT: discriminator +// DEBUGINFO-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} From 872a13faa58e663301bdb6c1a0518a79997164b9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 29 May 2026 23:51:40 +0200 Subject: [PATCH 4/6] Fix foreign items in rustdoc macro expansion feature --- src/librustdoc/html/macro_expansion.rs | 12 +++++++++++- .../macro-expansion/c-var-args.rs | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/macro-expansion/c-var-args.rs diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs index ec8b65984852c..4c820415e273c 100644 --- a/src/librustdoc/html/macro_expansion.rs +++ b/src/librustdoc/html/macro_expansion.rs @@ -2,7 +2,7 @@ use rustc_ast::visit::{ AssocCtxt, Visitor, walk_assoc_item, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt, walk_ty, }; -use rustc_ast::{AssocItem, Crate, Expr, Item, Pat, Stmt, Ty}; +use rustc_ast::{AssocItem, Crate, Expr, ForeignItem, Item, Pat, Stmt, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Span}; @@ -174,4 +174,14 @@ impl<'ast> Visitor<'ast> for ExpandedCodeVisitor<'ast> { walk_assoc_item(self, item, ctxt); } } + + fn visit_foreign_item(&mut self, item: &'ast ForeignItem) -> Self::Result { + if item.span.from_expansion() { + self.handle_new_span(item.span, || { + rustc_ast_pretty::pprust::foreign_item_to_string(item) + }); + } else { + walk_item(self, item); + } + } } diff --git a/tests/rustdoc-html/macro-expansion/c-var-args.rs b/tests/rustdoc-html/macro-expansion/c-var-args.rs new file mode 100644 index 0000000000000..1d42036cc7bf7 --- /dev/null +++ b/tests/rustdoc-html/macro-expansion/c-var-args.rs @@ -0,0 +1,19 @@ +// Ensure that C var args (`va_list`) work. +// Regression test for . + +//@ compile-flags: -Zunstable-options --generate-macro-expansion + +#![crate_name = "foo"] + +//@ has 'src/foo/c-var-args.rs.html' + +macro_rules! print { + () => { + fn printf(...); + }; +} + +//@ has - '//*[@class="expansion"]/*[@class="expanded"]' 'fn printf(...);' +extern "C" { + print! {} +} From 814e36f7c632ca4fb1d003fe67b059aaac079178 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 30 May 2026 12:10:40 +0200 Subject: [PATCH 5/6] Revert "drop derive helpers during ast lowering" This reverts commit 29e92731 --- compiler/rustc_attr_parsing/src/interface.rs | 23 +++----------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index eb49f108b0414..ffe0451f29aa9 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -285,11 +285,6 @@ impl<'sess> AttributeParser<'sess> { mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { let mut attributes = Vec::new(); - // We store the attributes we intend to discard at the end of this function in order to - // check they are applied to the right target and error out if necessary. In practice, we - // end up dropping only derive attributes and derive helpers, both being fully processed - // at macro expansion. - let mut dropped_attributes = Vec::new(); let mut attr_paths: Vec> = Vec::new(); let mut early_parsed_state = EarlyParsedState::default(); @@ -437,20 +432,8 @@ impl<'sess> AttributeParser<'sess> { self.check_invalid_crate_level_attr_item(&attr, n.item.span()); } - let attr = Attribute::Unparsed(Box::new(attr)); - - if self.tools.is_some_and(|tools| { - tools.iter().any(|tool| tool.name == parts[0]) - // FIXME: this can be removed once #152369 has been merged. - // https://github.com/rust-lang/rust/pull/152369 - || [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn] - .contains(&parts[0]) - }) { - attributes.push(attr); - } else { - dropped_attributes.push(attr); - } - } + attributes.push(Attribute::Unparsed(Box::new(attr))); + }; } } } @@ -466,7 +449,7 @@ impl<'sess> AttributeParser<'sess> { } if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate { - self.check_invalid_where_predicate_attrs(attributes.iter().chain(&dropped_attributes)); + self.check_invalid_where_predicate_attrs(attributes.iter()); } attributes From 5be84518f437d9872cb42322d32a80b39e17a6ec Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 30 May 2026 12:18:29 +0200 Subject: [PATCH 6/6] Add regression test --- tests/rustdoc-json/attrs/derive_helper.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 tests/rustdoc-json/attrs/derive_helper.rs diff --git a/tests/rustdoc-json/attrs/derive_helper.rs b/tests/rustdoc-json/attrs/derive_helper.rs new file mode 100644 index 0000000000000..278d0072decdd --- /dev/null +++ b/tests/rustdoc-json/attrs/derive_helper.rs @@ -0,0 +1,7 @@ +//@ is "$.index[?(@.name=='A')].attrs" '[{"other": "#[default]"}]' +#[derive(Default)] +pub enum Test { + #[default] + A, + B, +}