Change:
LLVM's "IR-level" instrumentation, which is used by to generate PGO instrumented binaries, does not yet work with exception handling on Windows MSVC. The problem has been reported to LLVM for C++ here: This also affects Rust programs built with for Windows MSVC. As long as LLVM does not support exception handling there, it is a known limitation that PGO can only be used with on this platform.
PGO does not yet work on for other reasons (see ). Once it does, we should check if this problem is specific to MSVC.
I have working x86_64 windows-gnu (64 bit builds use SEH) build with PGO I'll open PR once is merged. I can do testing in meantime. FWIW simple hello world example works fine after going through PGO.
if you test, be sure to compile your LLVM with assertions: Thanks for looking into it!
I'll recompile it with assertions today later. Should the test case be using any specific code like ?
The following test case runs into the problem with MSVC: See for how the file is compiled.
It does not reproduce with gnu toolchain with Rust and LLVM assertions enabled, I'll try to remember about fixing along with gnu profiler.
Cool!
I just confirmed that (for me locally) PGO seems to work on Windows GNU. That is, I built with instrumentation, ran it, and rebuilt it with the profiling data collected. It worked just fine, no crashes. So I updated the original issue text to just mention MSVC instead of Windows in general.
It looks like is a bit too aggressive with its error reporting. For example when invoking rustc, but not compiling in our Firefox build we can the following : I'm not sure the best solution while mw is away; perhaps we should revert for now.
Maybe we can just convert the error to a warning?
Not the best long-term solution but seems ok
It looks like the was marked fixed a year ago. What's the status of this issue in rustc?

Discussion:
use crate::cgu_reuse_tracker::CguReuseTracker; use crate::code_stats::CodeStats; pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; <del> use crate::config::{self, CrateType, OutputType, PrintRequest, SwitchWithOptPath}; </del> <ins> use crate::config::{self, CrateType, OutputType, SwitchWithOptPath}; </ins> use crate::filesearch; use crate::lint::{self, LintId}; use crate::parse::ParseSess;

} } <del> // PGO does not work reliably with panic=unwind on Windows. Let's make it // an error to combine the two for now. It always runs into an assertions // if LLVM is built with assertions, but without assertions it sometimes // does not crash and will probably generate a corrupted binary. // We should only display this error if we're actually going to run PGO. // If we're just supposed to print out some data, don't show the error (#61002). if sess.opts.cg.profile_generate.enabled() && sess.target.is_like_msvc && sess.panic_strategy() == PanicStrategy::Unwind && sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { sess.err( "Profile-guided optimization does not yet work in conjunction  with `-Cpanic=unwind` on Windows when targeting MSVC.  See issue #61002 <https://github.com/rust-lang/rust/issues/61002>  for more information.", ); } </del> // Sanitizers can only be used on platforms that we know have working sanitizer codegen. let supported_sanitizers = sess.target.options.supported_sanitizers; let unsupported_sanitizers = sess.opts.debugging_opts.sanitizer - supported_sanitizers;

// Test that `-Cprofile-generate` creates expected instrumentation artifacts in LLVM IR. <del> // Compiling with `-Cpanic=abort` because PGO+unwinding isn't supported on all platforms. </del> // needs-profiler-support <del> // compile-flags: -Cprofile-generate -Ccodegen-units=1 -Cpanic=abort </del> <ins> // compile-flags: -Cprofile-generate -Ccodegen-units=1 </ins> // CHECK: @__llvm_profile_raw_version = // CHECK-DAG: @__profc_{{.*}}pgo_instrumentation{{.*}}some_function{{.*}} = {{.*}}global

-include ../tools.mk <del> # This test makes sure that instrumented binaries record the right counts for # functions being called and branches being taken. We run an instrumented binary # with an argument that causes a know path through the program and then check # that the expected counts get added to the use-phase LLVM IR. # LLVM doesn't support instrumenting binaries that use SEH: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMMON_FLAGS=-Cpanic=abort endif </del> # For some very small programs GNU ld seems to not properly handle # instrumentation sections correctly. Neither Gold nor LLD have that problem. ifeq ($(UNAME),Linux)

COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)" <del> # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMPILE_FLAGS+= -Cpanic=abort endif </del> all: $(RUSTC) $(COMPILE_FLAGS) test.rs $(call RUN,test) || exit 1

COMPILE_FLAGS=-O -Ccodegen-units=1 -Cprofile-generate="$(TMPDIR)" <del> # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMPILE_FLAGS+= -Cpanic=abort endif </del> all: $(RUSTC) $(COMPILE_FLAGS) --emit=llvm-ir test.rs # We expect symbols starting with "__llvm_profile_".

COMPILE_FLAGS=-g -Cprofile-generate="$(TMPDIR)" <del> # LLVM doesn't yet support instrumenting binaries that use unwinding on MSVC: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMPILE_FLAGS+= -Cpanic=abort endif </del> all: $(RUSTC) $(COMPILE_FLAGS) test.rs $(call RUN,test) || exit 1

-include ../tools.mk <del> # This test makes sure that indirect call promotion is performed. The test # programs calls the same function a thousand times through a function pointer. # Only PGO data provides the information that it actually always is the same # function. We verify that the indirect call promotion pass inserts a check # whether it can make a direct call instead of the indirect call. # LLVM doesn't support instrumenting binaries that use SEH: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMMON_FLAGS=-Cpanic=abort endif </del> all: # We don't compile `opaque` with either optimizations or instrumentation. # We don't compile `opaque` with either optimizations or instrumentation.

COMMON_FLAGS=-Copt-level=2 -Ccodegen-units=1 -Cllvm-args=-disable-preinline <del> # LLVM doesn't support instrumenting binaries that use SEH: # https://github.com/rust-lang/rust/issues/61002 # # Things work fine with -Cpanic=abort though. ifdef IS_MSVC COMMON_FLAGS+= -Cpanic=abort endif </del> ifeq ($(UNAME),Darwin) # macOS does not have the `tac` command, but `tail -r` does the same thing TAC := tail -r