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

Reply via email to