From: Lishin <[email protected]>
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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/cccddf6d4c7e56a0926efa7abf41a769d2057b7f
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4748
gcc/rust/backend/rust-compile-drop.cc | 4 ++
.../errors/borrowck/rust-bir-drop-analysis.cc | 36 +++++++++++
.../errors/borrowck/rust-bir-drop-analysis.h | 11 +++-
.../errors/borrowck/rust-borrow-checker.cc | 4 +-
.../rust/execute/drop-whole-local-move.rs | 59 +++++++++++++++++++
5 files changed, 112 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/rust/execute/drop-whole-local-move.rs
diff --git a/gcc/rust/backend/rust-compile-drop.cc
b/gcc/rust/backend/rust-compile-drop.cc
index ab63e9751..d6bf79c07 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 006b07f22..09301d86e 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 c6298985a..2a52c1355 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 f93c5595e..ba2b7067d 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 000000000..4bb8ca5bf
--- /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
--
2.54.0