On 12/9/20 4:09 PM, Eric Gallager via Gcc-patches wrote:
On Fri, Dec 4, 2020 at 4:58 AM Erick Ochoa <
erick.oc...@theobroma-systems.com> wrote:


This commit includes the following components:

    Type-based escape analysis to determine structs that can be modified at
    link-time.
    Field access analysis to determine which fields are never read.

The type-based escape analysis provides a list of types, that are not
visible outside of the current linking unit (e.g. parameter types of
external
functions).

The field access analyses non-escaping structs for fields that
are not used in the linking unit and thus can be removed.

2020-11-04  Erick Ochoa  <erick.oc...@theobroma-systems.com>

      * Makefile.in: Add file to list of new sources.
      * common.opt: Add new flags.
      * ipa-type-escape-analysis.c: New file.
---
   gcc/Makefile.in                |    1 +
   gcc/common.opt                 |    8 +
   gcc/ipa-type-escape-analysis.c | 3428 ++++++++++++++++++++++++++++++++
   gcc/ipa-type-escape-analysis.h | 1152 +++++++++++
   gcc/passes.def                 |    1 +
   gcc/timevar.def                |    1 +
   gcc/tree-pass.h                |    2 +
   7 files changed, 4593 insertions(+)
   create mode 100644 gcc/ipa-type-escape-analysis.c
   create mode 100644 gcc/ipa-type-escape-analysis.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 978a08f7b04..8b18c9217a2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1415,6 +1415,7 @@ OBJS = \
         incpath.o \
         init-regs.o \
         internal-fn.o \
+       ipa-type-escape-analysis.o \
         ipa-cp.o \
         ipa-sra.o \
         ipa-devirt.o \
diff --git a/gcc/common.opt b/gcc/common.opt
index d4cbb2f86a5..85351738a29 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3460,4 +3460,12 @@ fipa-ra
   Common Report Var(flag_ipa_ra) Optimization
   Use caller save register across calls if possible.
   +fipa-type-escape-analysis
+Common Report Var(flag_ipa_type_escape_analysis) Optimization
+This flag is only used for debugging the type escape analysis
+
+Wdfa
+Common Var(warn_dfa) Init(1) Warning
+Warn about dead fields at link time.
+


I don't really like the name "-Wdfa" very much; could you maybe come up
with a longer and more descriptive name instead? Say, "-Wunused-field" or
"-Wunused-private-field" depending on the kind of field:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72789
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92801

I second that.  Also, invoke.texi needs to document the new option
and if it's only active with LTO it should mention that.  I looked
to see how the warning is used so I have some more comments on that
code (I didn't review the rest of the patch).


+// Obtain nonescaping unaccessed fields
+static record_field_offset_map_t
+obtain_nonescaping_unaccessed_fields (tpartitions_t casting,
+                                     record_field_map_t record_field_map)
+{
+  bool has_fields_that_can_be_deleted = false;
+  record_field_offset_map_t record_field_offset_map;
+  for (std::map<tree, field_access_map_t>::iterator i
+       = record_field_map.begin (),
+       e = record_field_map.end ();
+       i != e; ++i)
+    {
+      tree r_i = i->first;
+      std::vector<tree> equivalence
+       = find_equivalent_trees (r_i, record_field_map, casting);
+      field_offsets_t field_offset;
+      field_access_map_t original_field_map = record_field_map[r_i];
+      keep_only_read_fields_from_field_map (original_field_map,
field_offset);
+      keep_only_read_fields_from_equivalent_field_maps (equivalence,
+                                                       record_field_map,
+                                                       field_offset);
+      // These map holds the following:
+      // RECORD_TYPE -> unsigned (bit_pos_offset which has been read)
+      record_field_offset_map[r_i] = field_offset;
+    }
+
+  // So now that we only have the FIELDS which are read,
+  // we need to compute the complement...
+
+  // Improve: This is tightly coupled, I need to decouple it...
+  std::set<tree> to_erase;
+  std::set<tree> to_keep;
+  mark_escaping_types_to_be_deleted (record_field_offset_map, to_erase,
+                                    casting);
+  for (std::map<tree, field_offsets_t>::iterator i
+       = record_field_offset_map.begin (),
+       e = record_field_offset_map.end ();
+       i != e; ++i)
+    {
+      tree record = i->first;
+      const bool will_be_erased = to_erase.find (record) !=
to_erase.end ();
+      // No need to compute which fields can be deleted if type is
escaping
+      if (will_be_erased)
+       continue;
+
+      field_offsets_t field_offset = i->second;
+      for (tree field = TYPE_FIELDS (record); field; field = DECL_CHAIN
(field))
+       {
+         unsigned f_offset = bitpos_of_field (field);
+         bool in_set2 = field_offset.find (f_offset) != field_offset.end
();
+         if (in_set2)
+           {
+             field_offset.erase (f_offset);
+             continue;
+           }
+         to_keep.insert (record);
+         field_offset.insert (f_offset);
+         has_fields_that_can_be_deleted = true;
+         // NOTE: With anonymous fields this might be weird to print.
+         log ("%s.%s may be deleted\n",
+              type_stringifier::get_type_identifier (record).c_str (),
+              type_stringifier::get_field_identifier (field).c_str ());
+
+         if (OPT_Wdfa == 0) continue;

OPT_Wdfa is an enumerator so the above will never evaluate to true.
The warning() call checks to make sure a warning option is active
so checks like the above (which would otherwise use the warn_xxx
variable) aren't necessary, or really even reliable because they
don't faitfully reflect the state of warnings changed by #pragma
GCC diagnostic.


+         // Anonymous fields? (Which the record can be!).
+           warning (OPT_Wdfa, "RECORD_TYPE %qE has dead field %qE in
LTO.\n",
+               record, field);

The warning() call should really be warning_at() with the location
of the field (DECL_SOURCE_LOCATION (field). Otherwise I don't think
the location of this warning would be meaningful.

The RECORD_TYPE bit is a GCC-internal detail that shouldn't be
exposed in user-visible diagnostics.  If record is a type, %qT
should be used to format it (the directive mentions the class-id
('struct' or 'union' or 'class' in C++).

Warning text should also not end in a period or newline.  Most
of these formatting conventions are summarized in
  https://www.gnu.org/prep/standards/standards.html#Errors
and
  https://gcc.gnu.org/codingconventions.html#Diagnostics

If the warning isn't effective without LTO then specifying
the option without -flto should trigger a warning pointing it
out.  Otherwise users who expect it to work might be misled to
believe that their code is warning free.

Martin

Reply via email to