The fold_info hash_map stored fold_mem_info as heap-allocated pointers,
requiring a manual delete loop that was easy to miss on early returns.
Store it by value in the hash_map instead, which eliminates the memory
leak risk and simplifies the code by using get_or_insert in place of
new + put, and removing the manual delete loop entirely.

auto_bitmap is not movable (its move constructor is explicitly deleted),
so replace it with a raw bitmap pointer and add a constructor that
allocates the bitmap via BITMAP_ALLOC, a destructor that frees it, and
a move constructor that nulls the source pointer.  The move constructor
is required because hash_table::expand() explicitly destructs the source
entry after moving it, so without it the bitmap would be freed twice.

gcc/ChangeLog:

        * fold-mem-offsets.cc (fold_mem_info): Replace auto_bitmap with
        bitmap, adding constructor, destructor, and move constructor.
        (fold_info_map): Change value type from fold_mem_info * to
        fold_mem_info.
        (do_fold_info_calculation): Use get_or_insert instead of new
        and put.
        (compute_validity_closure): Access fold_mem_info by reference
        instead of pointer.
        (pass_fold_mem_offsets::execute): Access fold_mem_info via
        direct pointer from get, remove manual delete loop.
---

 gcc/fold-mem-offsets.cc | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc
index 2c1b7f154c01..bcc840ece0a5 100644
--- a/gcc/fold-mem-offsets.cc
+++ b/gcc/fold-mem-offsets.cc
@@ -129,11 +129,17 @@ public:
    of a memory instruction would increase by ADDED_OFFSET.  */
 class fold_mem_info {
 public:
-  auto_bitmap fold_insns;
+  fold_mem_info () : fold_insns (BITMAP_ALLOC (NULL)), added_offset (0) {}
+  ~fold_mem_info () { bitmap_obstack_free (fold_insns); }
+  fold_mem_info (fold_mem_info &&other) noexcept
+    : fold_insns (other.fold_insns), added_offset (other.added_offset)
+  { other.fold_insns = NULL; }
+
+  bitmap fold_insns;
   HOST_WIDE_INT added_offset;
 };
 
-typedef hash_map<rtx_insn *, fold_mem_info *> fold_info_map;
+typedef hash_map<rtx_insn *, fold_mem_info> fold_info_map;
 
 /* Tracks which instructions can be reached through instructions that can
    propagate offsets for folding.  */
@@ -673,10 +679,8 @@ do_fold_info_calculation (rtx_insn *insn, fold_info_map 
*fold_info)
   if (!get_fold_mem_root (insn, &mem, &reg, &cur_offset))
     return;
 
-  fold_mem_info *info = new fold_mem_info;
+  fold_mem_info *info = &fold_info->get_or_insert (insn);
   info->added_offset = fold_offsets (insn, reg, false, info->fold_insns);
-
-  fold_info->put (insn, info);
 }
 
 /* If INSN is a root memory instruction then compute a potentially new offset
@@ -749,10 +753,10 @@ compute_validity_closure (fold_info_map *fold_info)
       for (fold_info_map::iterator iter = fold_info->begin ();
           iter != fold_info->end (); ++iter)
        {
-         fold_mem_info *info = (*iter).second;
-         if (bitmap_intersect_p (&cannot_fold_insns, info->fold_insns))
+         fold_mem_info &info = (*iter).second;
+         if (bitmap_intersect_p (&cannot_fold_insns, info.fold_insns))
            made_changes |= bitmap_ior_into (&cannot_fold_insns,
-                                            info->fold_insns);
+                                            info.fold_insns);
        }
 
       if (!made_changes)
@@ -895,22 +899,18 @@ pass_fold_mem_offsets::execute (function *fn)
        do_fold_info_calculation (insn, &fold_info);
 
       FOR_BB_INSNS (bb, insn)
-       if (fold_mem_info **info = fold_info.get (insn))
-         do_check_validity (insn, *info);
+       if (fold_mem_info *info = fold_info.get (insn))
+         do_check_validity (insn, info);
 
       if (compute_validity_closure (&fold_info))
        {
          FOR_BB_INSNS (bb, insn)
-           if (fold_mem_info **info = fold_info.get (insn))
-             do_commit_offset (insn, *info);
+           if (fold_mem_info *info = fold_info.get (insn))
+             do_commit_offset (insn, info);
 
          FOR_BB_INSNS (bb, insn)
            do_commit_insn (insn);
        }
-
-      for (fold_info_map::iterator iter = fold_info.begin ();
-          iter != fold_info.end (); ++iter)
-       delete (*iter).second;
     }
 
   statistics_counter_event (cfun, "Number of folded instructions",
-- 
2.34.1

Reply via email to