https://gcc.gnu.org/g:c04842359618b7dd5b4dc86c62cde69e7020201d
commit r17-4112-gc04842359618b7dd5b4dc86c62cde69e7020201d Author: Lishin <[email protected]> Date: Sun Aug 2 15:03:11 2026 +0000 gccrs: Use BIR drop analysis in backend cleanup Connect the straight-line Drop analysis to the existing backend cleanup. Use the BIR analysis result to skip backend Drops for moved locals. Static and unclassified Drops keep the existing cleanup behavior. gcc/rust/ChangeLog: * backend/rust-compile-drop.cc (CompileDrop::build_current_scope_drop_cleanup): Skip definitely dead Drop candidates. * checks/errors/borrowck/rust-bir-drop-analysis.cc (DropAnalysis::get): New function. (DropAnalysis::clear): Likewise. (DropAnalysis::is_definitely_dead): Likewise. (DropAnalysis::analyze): Record dead whole-local HirIds. * checks/errors/borrowck/rust-bir-drop-analysis.h (DropAnalysis::get): New declaration. (DropAnalysis::clear): Likewise. (DropAnalysis::is_definitely_dead): Likewise. (DropAnalysis::definitely_dead): New member. * checks/errors/borrowck/rust-borrow-checker.cc (BorrowChecker::go): Clear old Drop analysis results and analyze each BIR function. gcc/testsuite/ChangeLog: * rust/execute/drop-whole-local-move.rs: New test. Signed-off-by: Lishin <[email protected]> Diff: --- gcc/rust/backend/rust-compile-drop.cc | 4 ++ .../errors/borrowck/rust-bir-drop-analysis.cc | 36 +++++++++++++ .../errors/borrowck/rust-bir-drop-analysis.h | 11 +++- .../checks/errors/borrowck/rust-borrow-checker.cc | 4 +- .../rust/execute/drop-whole-local-move.rs | 59 ++++++++++++++++++++++ 5 files changed, 112 insertions(+), 2 deletions(-) diff --git a/gcc/rust/backend/rust-compile-drop.cc b/gcc/rust/backend/rust-compile-drop.cc index ab63e9751146..d6bf79c07198 100644 --- a/gcc/rust/backend/rust-compile-drop.cc +++ b/gcc/rust/backend/rust-compile-drop.cc @@ -21,6 +21,7 @@ #include "rust-compile-base.h" #include "rust-compile-context.h" #include "rust-compile-implitem.h" +#include "rust-bir-drop-analysis.h" #include "rust-hir-path-probe.h" #include "rust-hir-trait-reference.h" #include "rust-hir-type-bounds.h" @@ -100,6 +101,9 @@ CompileDrop::build_current_scope_drop_cleanup () for (auto it = drop_candidates.rbegin (); it != drop_candidates.rend (); ++it) { + if (BIR::DropAnalysis::get ().is_definitely_dead (it->hirid)) + continue; + TyTy::BaseType *ty = nullptr; Bvariable *var = nullptr; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc index 006b07f22a19..09301d86eb62 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc @@ -18,6 +18,7 @@ #include "rust-bir-drop-analysis.h" #include "rust-bir.h" +#include "rust-hir-map.h" #include <unordered_set> @@ -36,6 +37,25 @@ struct BasicBlockIdHash } // namespace +DropAnalysis & +DropAnalysis::get () +{ + static DropAnalysis instance; + return instance; +} + +void +DropAnalysis::clear () +{ + definitely_dead.clear (); +} + +bool +DropAnalysis::is_definitely_dead (HirId id) const +{ + return definitely_dead.find (id) != definitely_dead.end (); +} + void DropAnalysis::analyze (Function &function) { @@ -106,6 +126,22 @@ DropAnalysis::analyze (Function &function) ? Statement::DropStyle::STATIC : Statement::DropStyle::DEAD); + if (statement.get_drop_style () == Statement::DropStyle::DEAD) + { + const Place &dropped_place = function.place_db[place]; + + if (dropped_place.kind == Place::VARIABLE) + { + auto hir_id + = Analysis::Mappings::get ().lookup_node_to_hir ( + static_cast<NodeId> ( + dropped_place.variable_or_field_index)); + + if (hir_id.has_value ()) + definitely_dead.insert (hir_id.value ()); + } + } + initialized[place.value] = false; break; diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.h b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.h index c6298985a54e..2a52c13550e6 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.h @@ -20,6 +20,7 @@ #define RUST_BIR_DROP_ANALYSIS_H #include "rust-bir.h" + namespace Rust { namespace BIR { @@ -32,7 +33,15 @@ namespace BIR { class DropAnalysis { public: - static void analyze (Function &function); + static DropAnalysis &get (); + + void clear (); + void analyze (Function &function); + + bool is_definitely_dead (HirId id) const; + +private: + std::set<HirId> definitely_dead; }; } // namespace BIR diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc index f93c5595ea8e..ba2b7067dca2 100644 --- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc +++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker.cc @@ -49,6 +49,8 @@ BorrowChecker::go (HIR::Crate &crate) { std::string crate_name; + BIR::DropAnalysis::get ().clear (); + if (enable_dump_bir) { mkdir ("bir_dump", 0755); @@ -70,7 +72,7 @@ BorrowChecker::go (HIR::Crate &crate) BIR::Builder builder (ctx); auto bir = builder.build (*func); - BIR::DropAnalysis::analyze (bir); + BIR::DropAnalysis::get ().analyze (bir); if (enable_dump_bir) { diff --git a/gcc/testsuite/rust/execute/drop-whole-local-move.rs b/gcc/testsuite/rust/execute/drop-whole-local-move.rs new file mode 100644 index 000000000000..4bb8ca5bf393 --- /dev/null +++ b/gcc/testsuite/rust/execute/drop-whole-local-move.rs @@ -0,0 +1,59 @@ +// { dg-output "^moved\r*\nstatic\r*\n$" } +// { dg-additional-options "-frust-borrowcheck -w" } + +#![feature(no_core)] +#![feature(lang_items)] +#![no_core] + +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "sized"] +pub trait Sized {} + +#[lang = "drop"] +pub trait Drop { + fn drop(&mut self); +} + +struct Moved { + value: i32, +} + +struct Static { + value: i32, +} + +impl Drop for Moved { + fn drop(&mut self) { + let msg = "moved\n\0" as *const str as *const i8; + unsafe { + printf(msg); + } + } +} + +impl Drop for Static { + fn drop(&mut self) { + let msg = "static\n\0" as *const str as *const i8; + unsafe { + printf(msg); + } + } +} + +fn whole_move() { + let x = Moved { value: 1 }; + let _y = x; +} + +fn static_local() { + let _x = Static { value: 2 }; +} + +fn main() -> i32 { + whole_move(); + static_local(); + 0 +} \ No newline at end of file
