]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-ssa.c
Update copyright years.
[thirdparty/gcc.git] / gcc / tree-ssa.c
index a67012c043faaac4a5967aa2ad3d143b0bece4d4..dbff604514574959072ba675b8b59aca62728b0f 100644 (file)
@@ -1,5 +1,5 @@
 /* Miscellaneous SSA utility functions.
-   Copyright (C) 2001-2017 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -41,6 +41,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgexpand.h"
 #include "tree-cfg.h"
 #include "tree-dfa.h"
+#include "stringpool.h"
+#include "attribs.h"
 #include "asan.h"
 
 /* Pointer map of variable mappings, keyed by edge.  */
@@ -50,7 +52,7 @@ static hash_map<edge, auto_vec<edge_var_map> > *edge_var_maps;
 /* Add a mapping with PHI RESULT and PHI DEF associated with edge E.  */
 
 void
-redirect_edge_var_map_add (edge e, tree result, tree def, source_location locus)
+redirect_edge_var_map_add (edge e, tree result, tree def, location_t locus)
 {
   edge_var_map new_node;
 
@@ -149,7 +151,7 @@ ssa_redirect_edge (edge e, basic_block dest)
     for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
       {
        tree def;
-       source_location locus ;
+       location_t locus;
 
        phi = gsi.phi ();
        def = gimple_phi_arg_def (phi, e->dest_idx);
@@ -218,7 +220,7 @@ flush_pending_stmts (edge e)
 void
 gimple_replace_ssa_lhs (gimple *stmt, tree nlhs)
 {
-  if (MAY_HAVE_DEBUG_STMTS)
+  if (MAY_HAVE_DEBUG_BIND_STMTS)
     {
       tree lhs = gimple_get_lhs (stmt);
 
@@ -240,7 +242,7 @@ gimple_replace_ssa_lhs (gimple *stmt, tree nlhs)
 tree
 target_for_debug_bind (tree var)
 {
-  if (!MAY_HAVE_DEBUG_STMTS)
+  if (!MAY_HAVE_DEBUG_BIND_STMTS)
     return NULL_TREE;
 
   if (TREE_CODE (var) == SSA_NAME)
@@ -305,7 +307,7 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
   int usecount = 0;
   tree value = NULL;
 
-  if (!MAY_HAVE_DEBUG_STMTS)
+  if (!MAY_HAVE_DEBUG_BIND_STMTS)
     return;
 
   /* If this name has already been registered for replacement, do nothing
@@ -356,6 +358,11 @@ insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
       else if (value == error_mark_node)
        value = NULL;
     }
+  else if (gimple_clobber_p (def_stmt))
+    /* We can end up here when rewriting a decl into SSA and coming
+       along a clobber for the original decl.  Turn that into
+       # DEBUG decl => NULL  */
+    value = NULL;
   else if (is_gimple_assign (def_stmt))
     {
       bool no_value = false;
@@ -493,7 +500,7 @@ insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
-  if (!MAY_HAVE_DEBUG_STMTS)
+  if (!MAY_HAVE_DEBUG_BIND_STMTS)
     return;
 
   stmt = gsi_stmt (*gsi);
@@ -519,7 +526,7 @@ reset_debug_uses (gimple *stmt)
   imm_use_iterator imm_iter;
   gimple *use_stmt;
 
-  if (!MAY_HAVE_DEBUG_STMTS)
+  if (!MAY_HAVE_DEBUG_BIND_STMTS)
     return;
 
   FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
@@ -552,20 +559,25 @@ release_defs_bitset (bitmap toremove)
 
   /* Performing a topological sort is probably overkill, this will
      most likely run in slightly superlinear time, rather than the
-     pathological quadratic worst case.  */
+     pathological quadratic worst case.
+     But iterate from max SSA name version to min one because
+     that mimics allocation order during code generation behavior best.
+     Use an array for this which we compact on-the-fly with a NULL
+     marker moving towards the end of the vector.  */
+  auto_vec<tree, 16> names;
+  names.reserve (bitmap_count_bits (toremove) + 1);
+  names.quick_push (NULL_TREE);
+  EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi)
+    names.quick_push (ssa_name (j));
+
+  bitmap_tree_view (toremove);
   while (!bitmap_empty_p (toremove))
     {
-      unsigned to_remove_bit = -1U;
-      EXECUTE_IF_SET_IN_BITMAP (toremove, 0, j, bi)
+      j = names.length () - 1;
+      for (unsigned i = names.length () - 1; names[i];)
        {
-         if (to_remove_bit != -1U)
-           {
-             bitmap_clear_bit (toremove, to_remove_bit);
-             to_remove_bit = -1U;
-           }
-
          bool remove_now = true;
-         tree var = ssa_name (j);
+         tree var = names[i];
          gimple *stmt;
          imm_use_iterator uit;
 
@@ -610,16 +622,26 @@ release_defs_bitset (bitmap toremove)
                  gsi_remove (&gsi, true);
                  release_defs (def);
                }
-
-             to_remove_bit = j;
+             bitmap_clear_bit (toremove, SSA_NAME_VERSION (var));
            }
+         else
+           --i;
+         if (--j != i)
+           names[i] = names[j];
        }
-      if (to_remove_bit != -1U)
-       bitmap_clear_bit (toremove, to_remove_bit);
     }
-
+  bitmap_list_view (toremove);
 }
 
+/* Disable warnings about missing quoting in GCC diagnostics for
+   the verification errors.  Their format strings don't follow GCC
+   diagnostic conventions and the calls are ultimately followed by
+   one to internal_error.  */
+#if __GNUC__ >= 10
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
 /* Verify virtual SSA form.  */
 
 bool
@@ -1186,6 +1208,9 @@ err:
   internal_error ("verify_ssa failed");
 }
 
+#if __GNUC__ >= 10
+#  pragma GCC diagnostic pop
+#endif
 
 /* Initialize global DFA and SSA structures.  */
 
@@ -1377,10 +1402,10 @@ maybe_rewrite_mem_ref_base (tree *tp, bitmap suitable_for_renaming)
        }
       else if (DECL_SIZE (sym)
               && TREE_CODE (DECL_SIZE (sym)) == INTEGER_CST
-              && mem_ref_offset (*tp) >= 0
-              && wi::leu_p (mem_ref_offset (*tp)
-                            + wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (*tp))),
-                            wi::to_offset (DECL_SIZE_UNIT (sym)))
+              && (known_subrange_p
+                  (mem_ref_offset (*tp),
+                   wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (*tp))),
+                   0, wi::to_offset (DECL_SIZE_UNIT (sym))))
               && (! INTEGRAL_TYPE_P (TREE_TYPE (*tp)) 
                   || (wi::to_offset (TYPE_SIZE (TREE_TYPE (*tp)))
                       == TYPE_PRECISION (TREE_TYPE (*tp))))
@@ -1425,15 +1450,16 @@ non_rewritable_mem_ref_base (tree ref)
       if (! DECL_P (decl))
        return NULL_TREE;
       if (! is_gimple_reg_type (TREE_TYPE (base))
-         || VOID_TYPE_P (TREE_TYPE (base)))
+         || VOID_TYPE_P (TREE_TYPE (base))
+         || TREE_THIS_VOLATILE (decl) != TREE_THIS_VOLATILE (base))
        return decl;
       if ((TREE_CODE (TREE_TYPE (decl)) == VECTOR_TYPE
           || TREE_CODE (TREE_TYPE (decl)) == COMPLEX_TYPE)
          && useless_type_conversion_p (TREE_TYPE (base),
                                        TREE_TYPE (TREE_TYPE (decl)))
-         && wi::fits_uhwi_p (mem_ref_offset (base))
-         && wi::gtu_p (wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
-                       mem_ref_offset (base))
+         && known_ge (mem_ref_offset (base), 0)
+         && known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
+                      mem_ref_offset (base))
          && multiple_of_p (sizetype, TREE_OPERAND (base, 1),
                            TYPE_SIZE_UNIT (TREE_TYPE (base))))
        return NULL_TREE;
@@ -1443,11 +1469,11 @@ non_rewritable_mem_ref_base (tree ref)
        return NULL_TREE;
       /* For integral typed extracts we can use a BIT_FIELD_REF.  */
       if (DECL_SIZE (decl)
-         && TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
-         && mem_ref_offset (base) >= 0
-         && wi::leu_p (mem_ref_offset (base)
-                       + wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (base))),
-                       wi::to_offset (DECL_SIZE_UNIT (decl)))
+         && TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
+         && (known_subrange_p
+             (mem_ref_offset (base),
+              wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (base))),
+              0, wi::to_poly_offset (DECL_SIZE_UNIT (decl))))
          /* ???  We can't handle bitfield precision extracts without
             either using an alternate type for the BIT_FIELD_REF and
             then doing a conversion or possibly adjusting the offset
@@ -1513,14 +1539,29 @@ non_rewritable_lvalue_p (tree lhs)
       if (DECL_P (decl)
          && VECTOR_TYPE_P (TREE_TYPE (decl))
          && TYPE_MODE (TREE_TYPE (decl)) != BLKmode
-         && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
-                             TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))), 0)
-         && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
-         && tree_int_cst_lt (TREE_OPERAND (lhs, 1),
-                             TYPE_SIZE_UNIT (TREE_TYPE (decl)))
-         && (tree_to_uhwi (TREE_OPERAND (lhs, 1))
-             % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
-       return false;
+         && known_ge (mem_ref_offset (lhs), 0)
+         && known_gt (wi::to_poly_offset (TYPE_SIZE_UNIT (TREE_TYPE (decl))),
+                      mem_ref_offset (lhs))
+         && multiple_of_p (sizetype, TREE_OPERAND (lhs, 1),
+                           TYPE_SIZE_UNIT (TREE_TYPE (lhs))))
+       {
+         poly_uint64 lhs_bits, nelts;
+         if (poly_int_tree_p (TYPE_SIZE (TREE_TYPE (lhs)), &lhs_bits)
+             && multiple_p (lhs_bits,
+                            tree_to_uhwi
+                              (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl)))),
+                            &nelts))
+           {
+             if (known_eq (nelts, 1u))
+               return false;
+             /* For sub-vector inserts the insert vector mode has to be
+                supported.  */
+             tree vtype = build_vector_type (TREE_TYPE (TREE_TYPE (decl)),
+                                             nelts);
+             if (TYPE_MODE (vtype) != BLKmode)
+               return false;
+           }
+       }
     }
 
   /* A vector-insert using a BIT_FIELD_REF is rewritable using
@@ -1563,6 +1604,12 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs,
          || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
     {
       TREE_ADDRESSABLE (var) = 0;
+      /* If we cleared TREE_ADDRESSABLE make sure DECL_GIMPLE_REG_P
+         is unset if we cannot rewrite the var into SSA.  */
+      if ((TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
+          || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE)
+         && bitmap_bit_p (not_reg_needs, DECL_UID (var)))
+       DECL_GIMPLE_REG_P (var) = 0;
       if (is_gimple_reg (var))
        bitmap_set_bit (suitable_for_renaming, DECL_UID (var));
       if (dump_file)
@@ -1852,20 +1899,35 @@ execute_update_addresses_taken (void)
                    && bitmap_bit_p (suitable_for_renaming, DECL_UID (sym))
                    && VECTOR_TYPE_P (TREE_TYPE (sym))
                    && TYPE_MODE (TREE_TYPE (sym)) != BLKmode
-                   && operand_equal_p (TYPE_SIZE_UNIT (TREE_TYPE (lhs)),
-                                       TYPE_SIZE_UNIT
-                                         (TREE_TYPE (TREE_TYPE (sym))), 0)
-                   && tree_fits_uhwi_p (TREE_OPERAND (lhs, 1))
-                   && tree_int_cst_lt (TREE_OPERAND (lhs, 1),
-                                       TYPE_SIZE_UNIT (TREE_TYPE (sym)))
-                   && (tree_to_uhwi (TREE_OPERAND (lhs, 1))
-                       % tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (lhs)))) == 0)
+                   /* If it is a full replacement we can do better below.  */
+                   && maybe_ne (wi::to_poly_offset
+                                  (TYPE_SIZE_UNIT (TREE_TYPE (lhs))),
+                                wi::to_poly_offset
+                                   (TYPE_SIZE_UNIT (TREE_TYPE (sym))))
+                   && known_ge (mem_ref_offset (lhs), 0)
+                   && known_gt (wi::to_poly_offset
+                                  (TYPE_SIZE_UNIT (TREE_TYPE (sym))),
+                                mem_ref_offset (lhs))
+                   && multiple_of_p (sizetype,
+                                     TREE_OPERAND (lhs, 1),
+                                     TYPE_SIZE_UNIT (TREE_TYPE (lhs))))
                  {
                    tree val = gimple_assign_rhs1 (stmt);
                    if (! types_compatible_p (TREE_TYPE (val),
                                              TREE_TYPE (TREE_TYPE (sym))))
                      {
-                       tree tem = make_ssa_name (TREE_TYPE (TREE_TYPE (sym)));
+                       poly_uint64 lhs_bits, nelts;
+                       tree temtype = TREE_TYPE (TREE_TYPE (sym));
+                       if (poly_int_tree_p (TYPE_SIZE (TREE_TYPE (lhs)),
+                                            &lhs_bits)
+                           && multiple_p (lhs_bits,
+                                          tree_to_uhwi
+                                            (TYPE_SIZE (TREE_TYPE
+                                                          (TREE_TYPE (sym)))),
+                                          &nelts)
+                           && maybe_ne (nelts, 1u))
+                         temtype = build_vector_type (temtype, nelts);
+                       tree tem = make_ssa_name (temtype);
                        gimple *pun
                          = gimple_build_assign (tem,
                                                 build1 (VIEW_CONVERT_EXPR,
@@ -1959,9 +2021,7 @@ execute_update_addresses_taken (void)
                            /* In ASAN_MARK (UNPOISON, &b, ...) the variable
                               is uninitialized.  Avoid dependencies on
                               previous out of scope value.  */
-                           tree clobber
-                             = build_constructor (TREE_TYPE (var), NULL);
-                           TREE_THIS_VOLATILE (clobber) = 1;
+                           tree clobber = build_clobber (TREE_TYPE (var));
                            gimple *g = gimple_build_assign (var, clobber);
                            gsi_replace (&gsi, g, GSI_SAME_STMT);
                          }