]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/tree-phinodes.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / tree-phinodes.c
index b9c5b43ea57be36f82a56221058a9716d810a4e6..e0cb60647593947d6a91805a72a1358636efb049 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic routines for manipulating PHIs
-   Copyright (C) 2003-2013 Free Software Foundation, Inc.
+   Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -20,22 +20,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
+#include "backend.h"
 #include "tree.h"
-#include "basic-block.h"
-#include "tree-ssa-alias.h"
-#include "internal-fn.h"
-#include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
+#include "ssa.h"
+#include "fold-const.h"
 #include "gimple-iterator.h"
-#include "gimple-ssa.h"
-#include "tree-phinodes.h"
-#include "ssa-iterators.h"
-#include "stringpool.h"
-#include "tree-ssanames.h"
 #include "tree-ssa.h"
-#include "diagnostic-core.h"
 
 /* Rewriting a function into SSA form can create a huge number of PHIs
    many of which may be thrown away shortly after their creation if jumps
@@ -76,7 +67,7 @@ along with GCC; see the file COPYING3.  If not see
    the -2 on all the calculations below.  */
 
 #define NUM_BUCKETS 10
-static GTY ((deletable (""))) vec<gimple, va_gc> *free_phinodes[NUM_BUCKETS - 2];
+static GTY ((deletable (""))) vec<gimple *, va_gc> *free_phinodes[NUM_BUCKETS - 2];
 static unsigned long free_phinode_count;
 
 static int ideal_phi_node_len (int);
@@ -89,20 +80,22 @@ unsigned int phi_nodes_created;
 void
 phinodes_print_statistics (void)
 {
-  fprintf (stderr, "PHI nodes allocated: %u\n", phi_nodes_created);
-  fprintf (stderr, "PHI nodes reused: %u\n", phi_nodes_reused);
+  fprintf (stderr, "%-32s" PRsa (11) "\n", "PHI nodes allocated:",
+          SIZE_AMOUNT (phi_nodes_created));
+  fprintf (stderr, "%-32s" PRsa (11) "\n", "PHI nodes reused:",
+          SIZE_AMOUNT (phi_nodes_reused));
 }
 
 /* Allocate a PHI node with at least LEN arguments.  If the free list
    happens to contain a PHI node with LEN arguments or more, return
    that one.  */
 
-static inline gimple_statement_phi *
+static inline gphi *
 allocate_phi_node (size_t len)
 {
-  gimple_statement_phi *phi;
+  gphi *phi;
   size_t bucket = NUM_BUCKETS - 2;
-  size_t size = sizeof (struct gimple_statement_phi)
+  size_t size = sizeof (struct gphi)
                + (len - 1) * sizeof (struct phi_arg_d);
 
   if (free_phinode_count)
@@ -115,7 +108,7 @@ allocate_phi_node (size_t len)
       && gimple_phi_capacity ((*free_phinodes[bucket])[0]) >= len)
     {
       free_phinode_count--;
-      phi = as_a <gimple_statement_phi> (free_phinodes[bucket]->pop ());
+      phi = as_a <gphi *> (free_phinodes[bucket]->pop ());
       if (free_phinodes[bucket]->is_empty ())
        vec_free (free_phinodes[bucket]);
       if (GATHER_STATISTICS)
@@ -123,8 +116,7 @@ allocate_phi_node (size_t len)
     }
   else
     {
-      phi = static_cast <gimple_statement_phi *> (
-       ggc_internal_alloc_stat (size MEM_STAT_INFO));
+      phi = static_cast <gphi *> (ggc_internal_alloc (size));
       if (GATHER_STATISTICS)
        {
          enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI);
@@ -158,7 +150,7 @@ ideal_phi_node_len (int len)
     len = 2;
 
   /* Compute the number of bytes of the original request.  */
-  size = sizeof (struct gimple_statement_phi)
+  size = sizeof (struct gphi)
         + (len - 1) * sizeof (struct phi_arg_d);
 
   /* Round it up to the next power of two.  */
@@ -173,10 +165,10 @@ ideal_phi_node_len (int len)
 
 /* Return a PHI node with LEN argument slots for variable VAR.  */
 
-static gimple
+static gphi *
 make_phi_node (tree var, int len)
 {
-  gimple_statement_phi *phi;
+  gphi *phi;
   int capacity, i;
 
   capacity = ideal_phi_node_len (len);
@@ -186,7 +178,7 @@ make_phi_node (tree var, int len)
   /* We need to clear the entire PHI node, including the argument
      portion, because we represent a "missing PHI argument" by placing
      NULL_TREE in PHI_ARG_DEF.  */
-  memset (phi, 0, (sizeof (struct gimple_statement_phi)
+  memset (phi, 0, (sizeof (struct gphi)
                   - sizeof (struct phi_arg_d)
                   + sizeof (struct phi_arg_d) * len));
   phi->code = GIMPLE_PHI;
@@ -200,7 +192,7 @@ make_phi_node (tree var, int len)
   else
     gimple_phi_set_result (phi, make_ssa_name (var, phi));
 
-  for (i = 0; i < capacity; i++)
+  for (i = 0; i < len; i++)
     {
       use_operand_p  imm;
 
@@ -217,8 +209,8 @@ make_phi_node (tree var, int len)
 
 /* We no longer need PHI, release it so that it may be reused.  */
 
-void
-release_phi_node (gimple phi)
+static void
+release_phi_node (gimple *phi)
 {
   size_t bucket;
   size_t len = gimple_phi_capacity (phi);
@@ -241,23 +233,27 @@ release_phi_node (gimple phi)
 /* Resize an existing PHI node.  The only way is up.  Return the
    possibly relocated phi.  */
 
-static gimple_statement_phi *
-resize_phi_node (gimple_statement_phi *phi, size_t len)
+static gphi *
+resize_phi_node (gphi *phi, size_t len)
 {
   size_t old_size, i;
-  gimple_statement_phi *new_phi;
+  gphi *new_phi;
 
   gcc_assert (len > gimple_phi_capacity (phi));
 
   /* The garbage collector will not look at the PHI node beyond the
      first PHI_NUM_ARGS elements.  Therefore, all we have to copy is a
      portion of the PHI node currently in use.  */
-  old_size = sizeof (struct gimple_statement_phi)
+  old_size = sizeof (struct gphi)
             + (gimple_phi_num_args (phi) - 1) * sizeof (struct phi_arg_d);
 
   new_phi = allocate_phi_node (len);
 
   memcpy (new_phi, phi, old_size);
+  memset ((char *)new_phi + old_size, 0,
+         (sizeof (struct gphi)
+          - sizeof (struct phi_arg_d)
+          + sizeof (struct phi_arg_d) * len) - old_size);
 
   for (i = 0; i < gimple_phi_num_args (new_phi); i++)
     {
@@ -270,18 +266,6 @@ resize_phi_node (gimple_statement_phi *phi, size_t len)
 
   new_phi->capacity = len;
 
-  for (i = gimple_phi_num_args (new_phi); i < len; i++)
-    {
-      use_operand_p imm;
-
-      gimple_phi_arg_set_location (new_phi, i, UNKNOWN_LOCATION);
-      imm = gimple_phi_arg_imm_use_ptr (new_phi, i);
-      imm->use = gimple_phi_arg_def_ptr (new_phi, i);
-      imm->prev = NULL;
-      imm->next = NULL;
-      imm->loc.stmt = new_phi;
-    }
-
   return new_phi;
 }
 
@@ -292,16 +276,15 @@ reserve_phi_args_for_new_edge (basic_block bb)
 {
   size_t len = EDGE_COUNT (bb->preds);
   size_t cap = ideal_phi_node_len (len + 4);
-  gimple_stmt_iterator gsi;
+  gphi_iterator gsi;
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      gimple_statement_phi *stmt =
-       as_a <gimple_statement_phi> (gsi_stmt (gsi));
+      gphi *stmt = gsi.phi ();
 
       if (len > gimple_phi_capacity (stmt))
        {
-         gimple_statement_phi *new_phi = resize_phi_node (stmt, cap);
+         gphi *new_phi = resize_phi_node (stmt, cap);
 
          /* The result of the PHI is defined by this PHI node.  */
          SSA_NAME_DEF_STMT (gimple_phi_result (new_phi)) = new_phi;
@@ -311,6 +294,8 @@ reserve_phi_args_for_new_edge (basic_block bb)
          stmt = new_phi;
        }
 
+      stmt->nargs++;
+
       /* We represent a "missing PHI argument" by placing NULL_TREE in
         the corresponding slot.  If PHI arguments were added
         immediately after an edge is created, this zeroing would not
@@ -318,17 +303,20 @@ reserve_phi_args_for_new_edge (basic_block bb)
         example, the loop optimizer duplicates several basic blocks,
         redirects edges, and then fixes up PHI arguments later in
         batch.  */
+      use_operand_p imm = gimple_phi_arg_imm_use_ptr (stmt, len - 1);
+      imm->use = gimple_phi_arg_def_ptr (stmt, len - 1);
+      imm->prev = NULL;
+      imm->next = NULL;
+      imm->loc.stmt = stmt;
       SET_PHI_ARG_DEF (stmt, len - 1, NULL_TREE);
       gimple_phi_arg_set_location (stmt, len - 1, UNKNOWN_LOCATION);
-
-      stmt->nargs++;
     }
 }
 
 /* Adds PHI to BB.  */
 
 void
-add_phi_node_to_bb (gimple phi, basic_block bb)
+add_phi_node_to_bb (gphi *phi, basic_block bb)
 {
   gimple_seq seq = phi_nodes (bb);
   /* Add the new PHI node to the list of PHI nodes for block BB.  */
@@ -347,10 +335,10 @@ add_phi_node_to_bb (gimple phi, basic_block bb)
 
 /* Create a new PHI node for variable VAR at basic block BB.  */
 
-gimple
+gphi *
 create_phi_node (tree var, basic_block bb)
 {
-  gimple phi = make_phi_node (var, EDGE_COUNT (bb->preds));
+  gphi *phi = make_phi_node (var, EDGE_COUNT (bb->preds));
 
   add_phi_node_to_bb (phi, bb);
   return phi;
@@ -364,7 +352,7 @@ create_phi_node (tree var, basic_block bb)
    PHI points to the reallocated phi node when we return.  */
 
 void
-add_phi_arg (gimple phi, tree def, edge e, source_location locus)
+add_phi_arg (gphi *phi, tree def, edge e, location_t locus)
 {
   basic_block bb = e->dest;
 
@@ -397,7 +385,7 @@ add_phi_arg (gimple phi, tree def, edge e, source_location locus)
    is consistent with how we remove an edge from the edge vector.  */
 
 static void
-remove_phi_arg_num (gimple_statement_phi *phi, int i)
+remove_phi_arg_num (gphi *phi, int i)
 {
   int num_elem = gimple_phi_num_args (phi);
 
@@ -433,10 +421,10 @@ remove_phi_arg_num (gimple_statement_phi *phi, int i)
 void
 remove_phi_args (edge e)
 {
-  gimple_stmt_iterator gsi;
+  gphi_iterator gsi;
 
   for (gsi = gsi_start_phis (e->dest); !gsi_end_p (gsi); gsi_next (&gsi))
-    remove_phi_arg_num (as_a <gimple_statement_phi> (gsi_stmt (gsi)),
+    remove_phi_arg_num (gsi.phi (),
                        e->dest_idx);
 }
 
@@ -449,7 +437,7 @@ remove_phi_args (edge e)
 void
 remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p)
 {
-  gimple phi = gsi_stmt (*gsi);
+  gimple *phi = gsi_stmt (*gsi);
 
   if (release_lhs_p)
     insert_debug_temps_for_defs (gsi);
@@ -468,7 +456,7 @@ remove_phi_node (gimple_stmt_iterator *gsi, bool release_lhs_p)
 void
 remove_phi_nodes (basic_block bb)
 {
-  gimple_stmt_iterator gsi;
+  gphi_iterator gsi;
 
   for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); )
     remove_phi_node (&gsi, true);
@@ -480,7 +468,7 @@ remove_phi_nodes (basic_block bb)
    NULL.  */
 
 tree
-degenerate_phi_result (gimple phi)
+degenerate_phi_result (gphi *phi)
 {
   tree lhs = gimple_phi_result (phi);
   tree val = NULL;