refactor SLP constant insertion and provde entry insert helper
[gcc.git] / gcc / loop-iv.c
index 207b5e2bfa384427ea3ecd3d9ed3842d6acaf7db..d7b3d90f047448f2976bdb0f0c6dde7d62b35467 100644 (file)
@@ -1,5 +1,5 @@
 /* Rtl-level induction variable analysis.
-   Copyright (C) 2004-2019 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -62,6 +62,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "dumpfile.h"
 #include "rtl-iter.h"
 #include "tree-ssa-loop-niter.h"
+#include "regs.h"
+#include "function-abi.h"
 
 /* Possible return values of iv_get_reaching_def.  */
 
@@ -85,10 +87,11 @@ enum iv_grd_result
 
 /* Information about a biv.  */
 
-struct biv_entry
+class biv_entry
 {
+public:
   unsigned regno;      /* The register of the biv.  */
-  struct rtx_iv iv;    /* Value of the biv.  */
+  class rtx_iv iv;     /* Value of the biv.  */
 };
 
 static bool clean_slate = true;
@@ -96,7 +99,7 @@ static bool clean_slate = true;
 static unsigned int iv_ref_table_size = 0;
 
 /* Table of rtx_ivs indexed by the df_ref uid field.  */
-static struct rtx_iv ** iv_ref_table;
+static class rtx_iv ** iv_ref_table;
 
 /* Induction variable stored at the reference.  */
 #define DF_REF_IV(REF) iv_ref_table[DF_REF_ID (REF)]
@@ -104,7 +107,7 @@ static struct rtx_iv ** iv_ref_table;
 
 /* The current loop.  */
 
-static struct loop *current_loop;
+static class loop *current_loop;
 
 /* Hashtable helper.  */
 
@@ -135,7 +138,7 @@ biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r)
 
 static hash_table<biv_entry_hasher> *bivs;
 
-static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *);
+static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *);
 
 /* Return the RTX code corresponding to the IV extend code EXTEND.  */
 static inline enum rtx_code
@@ -155,9 +158,9 @@ iv_extend_to_rtx_code (enum iv_extend_code extend)
 
 /* Dumps information about IV to FILE.  */
 
-extern void dump_iv_info (FILE *, struct rtx_iv *);
+extern void dump_iv_info (FILE *, class rtx_iv *);
 void
-dump_iv_info (FILE *file, struct rtx_iv *iv)
+dump_iv_info (FILE *file, class rtx_iv *iv)
 {
   if (!iv->base)
     {
@@ -203,9 +206,9 @@ check_iv_ref_table_size (void)
   if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ())
     {
       unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4);
-      iv_ref_table = XRESIZEVEC (struct rtx_iv *, iv_ref_table, new_size);
+      iv_ref_table = XRESIZEVEC (class rtx_iv *, iv_ref_table, new_size);
       memset (&iv_ref_table[iv_ref_table_size], 0,
-             (new_size - iv_ref_table_size) * sizeof (struct rtx_iv *));
+             (new_size - iv_ref_table_size) * sizeof (class rtx_iv *));
       iv_ref_table_size = new_size;
     }
 }
@@ -244,7 +247,7 @@ static void
 clear_iv_info (void)
 {
   unsigned i, n_defs = DF_DEFS_TABLE_SIZE ();
-  struct rtx_iv *iv;
+  class rtx_iv *iv;
 
   check_iv_ref_table_size ();
   for (i = 0; i < n_defs; i++)
@@ -264,7 +267,7 @@ clear_iv_info (void)
 /* Prepare the data for an induction variable analysis of a LOOP.  */
 
 void
-iv_analysis_loop_init (struct loop *loop)
+iv_analysis_loop_init (class loop *loop)
 {
   current_loop = loop;
 
@@ -302,7 +305,7 @@ latch_dominating_def (rtx reg, df_ref *def)
 {
   df_ref single_rd = NULL, adef;
   unsigned regno = REGNO (reg);
-  struct df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch);
+  class df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch);
 
   for (adef = DF_REG_DEF_CHAIN (regno); adef; adef = DF_REF_NEXT_REG (adef))
     {
@@ -385,7 +388,7 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def)
    consistency with other iv manipulation functions that may fail).  */
 
 static bool
-iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst)
+iv_constant (class rtx_iv *iv, scalar_int_mode mode, rtx cst)
 {
   iv->mode = mode;
   iv->base = cst;
@@ -402,7 +405,7 @@ iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst)
 /* Evaluates application of subreg to MODE on IV.  */
 
 static bool
-iv_subreg (struct rtx_iv *iv, scalar_int_mode mode)
+iv_subreg (class rtx_iv *iv, scalar_int_mode mode)
 {
   /* If iv is invariant, just calculate the new value.  */
   if (iv->step == const0_rtx
@@ -444,7 +447,7 @@ iv_subreg (struct rtx_iv *iv, scalar_int_mode mode)
 /* Evaluates application of EXTEND to MODE on IV.  */
 
 static bool
-iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode)
+iv_extend (class rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode)
 {
   /* If iv is invariant, just calculate the new value.  */
   if (iv->step == const0_rtx
@@ -482,7 +485,7 @@ iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode)
 /* Evaluates negation of IV.  */
 
 static bool
-iv_neg (struct rtx_iv *iv)
+iv_neg (class rtx_iv *iv)
 {
   if (iv->extend == IV_UNKNOWN_EXTEND)
     {
@@ -505,7 +508,7 @@ iv_neg (struct rtx_iv *iv)
 /* Evaluates addition or subtraction (according to OP) of IV1 to IV0.  */
 
 static bool
-iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
+iv_add (class rtx_iv *iv0, class rtx_iv *iv1, enum rtx_code op)
 {
   scalar_int_mode mode;
   rtx arg;
@@ -575,7 +578,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op)
 /* Evaluates multiplication of IV by constant CST.  */
 
 static bool
-iv_mult (struct rtx_iv *iv, rtx mby)
+iv_mult (class rtx_iv *iv, rtx mby)
 {
   scalar_int_mode mode = iv->extend_mode;
 
@@ -600,7 +603,7 @@ iv_mult (struct rtx_iv *iv, rtx mby)
 /* Evaluates shift of IV by constant CST.  */
 
 static bool
-iv_shift (struct rtx_iv *iv, rtx mby)
+iv_shift (class rtx_iv *iv, rtx mby)
 {
   scalar_int_mode mode = iv->extend_mode;
 
@@ -810,9 +813,9 @@ get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg,
 /* Records information that DEF is induction variable IV.  */
 
 static void
-record_iv (df_ref def, struct rtx_iv *iv)
+record_iv (df_ref def, class rtx_iv *iv)
 {
-  struct rtx_iv *recorded_iv = XNEW (struct rtx_iv);
+  class rtx_iv *recorded_iv = XNEW (class rtx_iv);
 
   *recorded_iv = *iv;
   check_iv_ref_table_size ();
@@ -823,9 +826,9 @@ record_iv (df_ref def, struct rtx_iv *iv)
    IV and return true.  Otherwise return false.  */
 
 static bool
-analyzed_for_bivness_p (rtx def, struct rtx_iv *iv)
+analyzed_for_bivness_p (rtx def, class rtx_iv *iv)
 {
-  struct biv_entry *biv = bivs->find_with_hash (def, REGNO (def));
+  class biv_entry *biv = bivs->find_with_hash (def, REGNO (def));
 
   if (!biv)
     return false;
@@ -835,9 +838,9 @@ analyzed_for_bivness_p (rtx def, struct rtx_iv *iv)
 }
 
 static void
-record_biv (rtx def, struct rtx_iv *iv)
+record_biv (rtx def, class rtx_iv *iv)
 {
-  struct biv_entry *biv = XNEW (struct biv_entry);
+  class biv_entry *biv = XNEW (class biv_entry);
   biv_entry **slot = bivs->find_slot_with_hash (def, REGNO (def), INSERT);
 
   biv->regno = REGNO (def);
@@ -850,7 +853,7 @@ record_biv (rtx def, struct rtx_iv *iv)
    to *IV.  OUTER_MODE is the mode of DEF.  */
 
 static bool
-iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv)
+iv_analyze_biv (scalar_int_mode outer_mode, rtx def, class rtx_iv *iv)
 {
   rtx inner_step, outer_step;
   scalar_int_mode inner_mode;
@@ -928,11 +931,11 @@ iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv)
 
 bool
 iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs,
-                struct rtx_iv *iv)
+                class rtx_iv *iv)
 {
   rtx mby = NULL_RTX;
   rtx op0 = NULL_RTX, op1 = NULL_RTX;
-  struct rtx_iv iv0, iv1;
+  class rtx_iv iv0, iv1;
   enum rtx_code code = GET_CODE (rhs);
   scalar_int_mode omode = mode;
 
@@ -1039,7 +1042,7 @@ iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs,
 /* Analyzes iv DEF and stores the result to *IV.  */
 
 static bool
-iv_analyze_def (df_ref def, struct rtx_iv *iv)
+iv_analyze_def (df_ref def, class rtx_iv *iv)
 {
   rtx_insn *insn = DF_REF_INSN (def);
   rtx reg = DF_REF_REG (def);
@@ -1103,7 +1106,7 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
    mode of OP.  */
 
 static bool
-iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv)
+iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, class rtx_iv *iv)
 {
   df_ref def = NULL;
   enum iv_grd_result res;
@@ -1164,7 +1167,7 @@ iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv)
    mode of VAL.  */
 
 bool
-iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv)
+iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, class rtx_iv *iv)
 {
   rtx reg;
 
@@ -1189,7 +1192,7 @@ iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv)
 /* Analyzes definition of DEF in INSN and stores the result to IV.  */
 
 bool
-iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv)
+iv_analyze_result (rtx_insn *insn, rtx def, class rtx_iv *iv)
 {
   df_ref adef;
 
@@ -1209,7 +1212,7 @@ iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv)
 bool
 biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg)
 {
-  struct rtx_iv iv;
+  class rtx_iv iv;
   df_ref def, last_def;
 
   if (!simple_reg_p (reg))
@@ -1231,7 +1234,7 @@ biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg)
 /* Calculates value of IV at ITERATION-th iteration.  */
 
 rtx
-get_iv_value (struct rtx_iv *iv, rtx iteration)
+get_iv_value (class rtx_iv *iv, rtx iteration)
 {
   rtx val;
 
@@ -1381,24 +1384,23 @@ simple_rhs_p (rtx rhs)
 static rtx
 find_single_def_src (unsigned int regno)
 {
-  df_ref adef;
-  rtx set, src;
+  rtx src = NULL_RTX;
 
-  for (;;)
+  /* Don't look through unbounded number of single definition REG copies,
+     there might be loops for sources with uninitialized variables.  */
+  for (int cnt = 0; cnt < 128; cnt++)
     {
-      rtx note;
-      adef = DF_REG_DEF_CHAIN (regno);
+      df_ref adef = DF_REG_DEF_CHAIN (regno);
       if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL
          || DF_REF_IS_ARTIFICIAL (adef))
        return NULL_RTX;
 
-      set = single_set (DF_REF_INSN (adef));
+      rtx set = single_set (DF_REF_INSN (adef));
       if (set == NULL || !REG_P (SET_DEST (set))
          || REGNO (SET_DEST (set)) != regno)
        return NULL_RTX;
 
-      note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
-
+      rtx note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
       if (note && function_invariant_p (XEXP (note, 0)))
        {
          src = XEXP (note, 0);
@@ -1850,7 +1852,7 @@ eliminate_implied_conditions (enum rtx_code op, rtx *head, rtx tail)
    is a list, its elements are assumed to be combined using OP.  */
 
 static void
-simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
+simplify_using_initial_values (class loop *loop, enum rtx_code op, rtx *expr)
 {
   bool expression_valid;
   rtx head, tail, last_valid_expr;
@@ -1969,15 +1971,15 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
            continue;
 
          CLEAR_REG_SET (this_altered);
-         note_stores (PATTERN (insn), mark_altered, this_altered);
+         note_stores (insn, mark_altered, this_altered);
          if (CALL_P (insn))
            {
-             /* Kill all call clobbered registers.  */
-             unsigned int i;
-             hard_reg_set_iterator hrsi;
-             EXECUTE_IF_SET_IN_HARD_REG_SET (regs_invalidated_by_call,
-                                             0, i, hrsi)
-               SET_REGNO_REG_SET (this_altered, i);
+             /* Kill all registers that might be clobbered by the call.
+                We don't track modes of hard registers, so we need to be
+                conservative and assume that partial kills are full kills.  */
+             function_abi callee_abi = insn_callee_abi (insn);
+             IOR_REG_SET_HRS (this_altered,
+                              callee_abi.full_and_partial_reg_clobbers ());
            }
 
          if (suitable_set_for_replacement (insn, &dest, &src))
@@ -2071,8 +2073,8 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
    is SIGNED_P to DESC.  */
 
 static void
-shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode,
-                  enum rtx_code cond, bool signed_p, struct niter_desc *desc)
+shorten_into_mode (class rtx_iv *iv, scalar_int_mode mode,
+                  enum rtx_code cond, bool signed_p, class niter_desc *desc)
 {
   rtx mmin, mmax, cond_over, cond_under;
 
@@ -2130,8 +2132,8 @@ shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode,
    some assumptions to DESC).  */
 
 static bool
-canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
-                        enum rtx_code cond, struct niter_desc *desc)
+canonicalize_iv_subregs (class rtx_iv *iv0, class rtx_iv *iv1,
+                        enum rtx_code cond, class niter_desc *desc)
 {
   scalar_int_mode comp_mode;
   bool signed_p;
@@ -2246,7 +2248,7 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
    expression for the number of iterations, before we tried to simplify it.  */
 
 static uint64_t
-determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter)
+determine_max_iter (class loop *loop, class niter_desc *desc, rtx old_niter)
 {
   rtx niter = desc->niter_expr;
   rtx mmin, mmax, cmp;
@@ -2304,11 +2306,11 @@ determine_max_iter (struct loop *loop, struct niter_desc *desc, rtx old_niter)
    (basically its rtl version), complicated by things like subregs.  */
 
 static void
-iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
-                        struct niter_desc *desc)
+iv_number_of_iterations (class loop *loop, rtx_insn *insn, rtx condition,
+                        class niter_desc *desc)
 {
   rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1;
-  struct rtx_iv iv0, iv1;
+  class rtx_iv iv0, iv1;
   rtx assumption, may_not_xform;
   enum rtx_code cond;
   machine_mode nonvoid_mode;
@@ -2866,7 +2868,7 @@ fail:
    into DESC.  */
 
 static void
-check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
+check_simple_exit (class loop *loop, edge e, class niter_desc *desc)
 {
   basic_block exit_bb;
   rtx condition;
@@ -2913,13 +2915,13 @@ check_simple_exit (struct loop *loop, edge e, struct niter_desc *desc)
 
 /* Finds a simple exit of LOOP and stores its description into DESC.  */
 
-void
-find_simple_exit (struct loop *loop, struct niter_desc *desc)
+static void
+find_simple_exit (class loop *loop, class niter_desc *desc)
 {
   unsigned i;
   basic_block *body;
   edge e;
-  struct niter_desc act;
+  class niter_desc act;
   bool any = false;
   edge_iterator ei;
 
@@ -3017,10 +3019,10 @@ find_simple_exit (struct loop *loop, struct niter_desc *desc)
 /* Creates a simple loop description of LOOP if it was not computed
    already.  */
 
-struct niter_desc *
-get_simple_loop_desc (struct loop *loop)
+class niter_desc *
+get_simple_loop_desc (class loop *loop)
 {
-  struct niter_desc *desc = simple_loop_desc (loop);
+  class niter_desc *desc = simple_loop_desc (loop);
 
   if (desc)
     return desc;
@@ -3037,9 +3039,9 @@ get_simple_loop_desc (struct loop *loop)
 /* Releases simple loop description for LOOP.  */
 
 void
-free_simple_loop_desc (struct loop *loop)
+free_simple_loop_desc (class loop *loop)
 {
-  struct niter_desc *desc = simple_loop_desc (loop);
+  class niter_desc *desc = simple_loop_desc (loop);
 
   if (!desc)
     return;