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, ®, &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