]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add CLOBBER_EOL to mark storage end-of-life clobbers
authorRichard Biener <rguenther@suse.de>
Wed, 2 Feb 2022 13:24:39 +0000 (14:24 +0100)
committerRichard Biener <rguenther@suse.de>
Fri, 4 Feb 2022 07:16:50 +0000 (08:16 +0100)
This adds a flag to CONSTRUCTOR nodes indicating that for
clobbers this marks the end-of-life of storage as opposed to
just ending the lifetime of the object that occupied it.
The dangling pointer diagnostics uses CLOBBERs but is confused
by those emitted by the C++ frontend for example which emits
them for the second purpose at the start of CTORs.  The issue
is also appearant for aarch64 in PR104092.

Distinguishing the two cases is also necessary for the PR90348 fix.

Since I'm going to add another flag I added an enum clobber_flags
and a defaulted argument to build_clobber plus a convenient way to
query the enum from the CTOR tree and specify it for gimple_clobber_p.
Since 'CLOBBER' is already taken and I needed a name for the unspecified
clobber we have now I used 'CLOBBER_UNDEF'.

2022-02-03  Richard Biener  <rguenther@suse.de>

PR middle-end/90348
PR middle-end/104092
gcc/
* tree-core.h (clobber_kind): New enum.
(tree_base::u::bits::address_space): Document use in CONSTRUCTORs.
* tree.h (CLOBBER_KIND): Add.
(build_clobber): Add clobber kind argument, defaulted to
CLOBBER_UNDEF.
* tree.cc (build_clobber): Likewise.
* gimple.h (gimple_clobber_p): New overload with specified kind.
* tree-streamer-in.cc (streamer_read_tree_bitfields): Stream
CLOBBER_KIND.
* tree-streamer-out.cc (streamer_write_tree_bitfields):
Likewise.
* tree-pretty-print.cc (dump_generic_node): Mark EOL CLOBBERs.
* gimplify.cc (gimplify_bind_expr): Build storage end-of-life clobbers
with CLOBBER_EOL.
(gimplify_target_expr): Likewise.
* tree-inline.cc (expand_call_inline): Likewise.
* tree-ssa-ccp.cc (insert_clobber_before_stack_restore): Likewise.
* gimple-ssa-warn-access.cc (pass_waccess::check_stmt): Only treat
CLOBBER_EOL clobbers as ending lifetime of storage.

gcc/lto/
* lto-common.cc (compare_tree_sccs_1): Compare CLOBBER_KIND.

gcc/testsuite/
* gcc.dg/pr87052.c: Adjust.

13 files changed:
gcc/gimple-ssa-warn-access.cc
gcc/gimple.h
gcc/gimplify.cc
gcc/lto/lto-common.cc
gcc/testsuite/gcc.dg/pr87052.c
gcc/tree-core.h
gcc/tree-inline.cc
gcc/tree-pretty-print.cc
gcc/tree-ssa-ccp.cc
gcc/tree-streamer-in.cc
gcc/tree-streamer-out.cc
gcc/tree.cc
gcc/tree.h

index 4b3d2c00b0331583d426184578fc5bde8a422af7..80d41ea4383aae5d1121a59911e581259ce225f5 100644 (file)
@@ -4328,7 +4328,8 @@ is_auto_decl (tree x)
 void
 pass_waccess::check_stmt (gimple *stmt)
 {
-  if (m_check_dangling_p && gimple_clobber_p (stmt))
+  if (m_check_dangling_p
+      && gimple_clobber_p (stmt, CLOBBER_EOL))
     {
       /* Ignore clobber statemts in blocks with exceptional edges.  */
       basic_block bb = gimple_bb (stmt);
index 441d29a109a4183aab0dac9ff5a413477ec1bf68..77a5a07e9b5a2a447f2e2e82e0455cb69994aa6c 100644 (file)
@@ -2939,6 +2939,15 @@ gimple_clobber_p (const gimple *s)
          && TREE_CLOBBER_P (gimple_assign_rhs1 (s));
 }
 
+/* Return true if S is a clobber statement.  */
+
+static inline bool
+gimple_clobber_p (const gimple *s, enum clobber_kind kind)
+{
+  return gimple_clobber_p (s)
+        && CLOBBER_KIND (gimple_assign_rhs1 (s)) == kind;
+}
+
 /* Return true if GS is a GIMPLE_CALL.  */
 
 static inline bool
index cd4b61362b459a59d725831a54ef87a010ec4b49..875b115d02d5b9b560bbe25b22b85bf589115f41 100644 (file)
@@ -1475,7 +1475,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
              && !is_gimple_reg (t)
              && flag_stack_reuse != SR_NONE)
            {
-             tree clobber = build_clobber (TREE_TYPE (t));
+             tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_EOL);
              gimple *clobber_stmt;
              clobber_stmt = gimple_build_assign (t, clobber);
              gimple_set_location (clobber_stmt, end_locus);
@@ -6981,7 +6981,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
        {
          if (flag_stack_reuse == SR_ALL)
            {
-             tree clobber = build_clobber (TREE_TYPE (temp));
+             tree clobber = build_clobber (TREE_TYPE (temp), CLOBBER_EOL);
              clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
              gimple_push_cleanup (temp, clobber, false, pre_p, true);
            }
index 11fde671162885f265b8b6c9919ba61501e71aad..ca28586a1e8089fbd28a11f8162c780f5192a1b3 100644 (file)
@@ -1309,7 +1309,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
       return false;
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
-    compare_values (CONSTRUCTOR_NELTS);
+    {
+      compare_values (CLOBBER_KIND);
+      compare_values (CONSTRUCTOR_NELTS);
+    }
 
   if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
     if (IDENTIFIER_LENGTH (t1) != IDENTIFIER_LENGTH (t2)
index 2affc480f4e3778b1098b4ad0dd9270a007f14b6..18e092c46744ea42a761e1034e30fc721d4c6496 100644 (file)
@@ -38,4 +38,4 @@ void test (void)
    { dg-final { scan-tree-dump-times "c = \"\";"  1 "gimple" } }
    { dg-final { scan-tree-dump-times "d = { *};"  1 "gimple" } }
    { dg-final { scan-tree-dump-times "e = "  1 "gimple" } }
-   { dg-final { scan-tree-dump-times "e = {CLOBBER}"  1 "gimple" } }  */
+   { dg-final { scan-tree-dump-times "e = {CLOBBER\\(eol\\)}"  1 "gimple" } }  */
index e83669f20d8bb5d671419490a56a1caa56d3df7e..bf2efa613307132bf2cdd4be0151386a05de4632 100644 (file)
@@ -963,6 +963,15 @@ enum annot_expr_kind {
   annot_expr_kind_last
 };
 
+/* The kind of a TREE_CLOBBER_P CONSTRUCTOR node.  */
+enum clobber_kind {
+  /* Unspecified, this clobber acts as a store of an undefined value.  */
+  CLOBBER_UNDEF,
+  /* This clobber ends the lifetime of the storage.  */
+  CLOBBER_EOL,
+  CLOBBER_LAST
+};
+
 /*---------------------------------------------------------------------------
                                 Type definitions
 ---------------------------------------------------------------------------*/
@@ -1055,7 +1064,8 @@ struct GTY(()) tree_base {
 
       /* This field is only used with TREE_TYPE nodes; the only reason it is
         present in tree_base instead of tree_type is to save space.  The size
-        of the field must be large enough to hold addr_space_t values.  */
+        of the field must be large enough to hold addr_space_t values.
+        For CONSTRUCTOR nodes this holds the clobber_kind enum.  */
       unsigned address_space : 8;
     } bits;
 
index 497aa667eb958aa996786c072e6f01c03f0f9a30..ca66a8266b14de42c8c10917b06239aaf93a9758 100644 (file)
@@ -5138,7 +5138,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
              && !is_gimple_reg (*varp)
              && !(id->debug_map && id->debug_map->get (p)))
            {
-             tree clobber = build_clobber (TREE_TYPE (*varp));
+             tree clobber = build_clobber (TREE_TYPE (*varp), CLOBBER_EOL);
              gimple *clobber_stmt;
              clobber_stmt = gimple_build_assign (*varp, clobber);
              gimple_set_location (clobber_stmt, gimple_location (stmt));
@@ -5207,7 +5207,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
          && !is_gimple_reg (id->retvar)
          && !stmt_ends_bb_p (stmt))
        {
-         tree clobber = build_clobber (TREE_TYPE (id->retvar));
+         tree clobber = build_clobber (TREE_TYPE (id->retvar), CLOBBER_EOL);
          gimple *clobber_stmt;
          clobber_stmt = gimple_build_assign (id->retvar, clobber);
          gimple_set_location (clobber_stmt, gimple_location (old_stmt));
index 6130c307e9af984ef0d10b29fca5a8e244d5503e..666b7a70ea2d5c90dbbfe03ac57f92058a90fa63 100644 (file)
@@ -2500,7 +2500,11 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
          }
        pp_left_brace (pp);
        if (TREE_CLOBBER_P (node))
-         pp_string (pp, "CLOBBER");
+         {
+           pp_string (pp, "CLOBBER");
+           if (CLOBBER_KIND (node) == CLOBBER_EOL)
+             pp_string (pp, "(eol)");
+         }
        else if (TREE_CODE (TREE_TYPE (node)) == RECORD_TYPE
                 || TREE_CODE (TREE_TYPE (node)) == UNION_TYPE)
          is_struct_init = true;
index 48683f04d4959298d2f68989b8b802a6bc3518dd..9164efe30370199c7a2b972593336508d287c35f 100644 (file)
@@ -2505,7 +2505,7 @@ insert_clobber_before_stack_restore (tree saved_val, tree var,
   FOR_EACH_IMM_USE_STMT (stmt, iter, saved_val)
     if (gimple_call_builtin_p (stmt, BUILT_IN_STACK_RESTORE))
       {
-       clobber = build_clobber (TREE_TYPE (var));
+       clobber = build_clobber (TREE_TYPE (var), CLOBBER_EOL);
        clobber_stmt = gimple_build_assign (var, clobber);
 
        i = gsi_for_stmt (stmt);
index 65cdf125a70778550b15ca2249b990399a125ccb..a35a810f4d100240341bb3d3421a77505d82c403 100644 (file)
@@ -559,6 +559,8 @@ streamer_read_tree_bitfields (class lto_input_block *ib,
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
     {
+      CLOBBER_KIND (expr)
+       = bp_unpack_enum (&bp, clobber_kind, CLOBBER_LAST);
       unsigned HOST_WIDE_INT length = bp_unpack_var_len_unsigned (&bp);
       if (length > 0)
        vec_safe_grow (CONSTRUCTOR_ELTS (expr), length, true);
index 783b94dd094cd448da258de5deb935cb6499d95d..d39dc158a4650d802d9f3dc6feed99e4749aab37 100644 (file)
@@ -504,7 +504,10 @@ streamer_write_tree_bitfields (struct output_block *ob, tree expr)
     cl_optimization_stream_out (ob, &bp, TREE_OPTIMIZATION (expr));
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
-    bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr));
+    {
+      bp_pack_enum (&bp, clobber_kind, CLOBBER_LAST, CLOBBER_KIND (expr));
+      bp_pack_var_len_unsigned (&bp, CONSTRUCTOR_NELTS (expr));
+    }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)
       /* Don't stream these when passing things to a different target.  */
index 7ce4f242751a9856ebaede03221578f4ab76ea78..dfcdf6822f136b8ea3d085429945938f94d776bc 100644 (file)
@@ -2311,10 +2311,11 @@ build_constructor_va (tree type, int nelts, ...)
 /* Return a node of type TYPE for which TREE_CLOBBER_P is true.  */
 
 tree
-build_clobber (tree type)
+build_clobber (tree type, enum clobber_kind kind)
 {
   tree clobber = build_constructor (type, NULL);
   TREE_THIS_VOLATILE (clobber) = true;
+  CLOBBER_KIND (clobber) = kind;
   return clobber;
 }
 
index e2157d66d6c77bd12054d07a62db4999de7f9fda..95334b077da020066db68eae88c4002433b4d6c9 100644 (file)
@@ -1155,6 +1155,10 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 #define TREE_CLOBBER_P(NODE) \
   (TREE_CODE (NODE) == CONSTRUCTOR && TREE_THIS_VOLATILE (NODE))
 
+/* Return the clobber_kind of a CLOBBER CONSTRUCTOR.  */
+#define CLOBBER_KIND(NODE) \
+  (CONSTRUCTOR_CHECK (NODE)->base.u.bits.address_space)
+
 /* Define fields and accessors for some nodes that represent expressions.  */
 
 /* Nonzero if NODE is an empty statement (NOP_EXPR <0>).  */
@@ -4559,7 +4563,7 @@ extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
 extern tree build_constructor_from_vec (tree, const vec<tree, va_gc> *);
 extern tree build_constructor_va (tree, int, ...);
-extern tree build_clobber (tree);
+extern tree build_clobber (tree, enum clobber_kind = CLOBBER_UNDEF);
 extern tree build_real_from_int_cst (tree, const_tree);
 extern tree build_real_from_wide (tree, const wide_int_ref &, signop);
 extern tree build_complex (tree, tree, tree);