diff gcc/loop-iv.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/loop-iv.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/loop-iv.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* Rtl-level induction variable analysis.
-   Copyright (C) 2004-2018 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -61,6 +61,9 @@
 #include "intl.h"
 #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.  */
 
@@ -84,10 +87,11 @@
 
 /* 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;
@@ -95,7 +99,7 @@
 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)]
@@ -103,7 +107,7 @@
 
 /* The current loop.  */
 
-static struct loop *current_loop;
+static class loop *current_loop;
 
 /* Hashtable helper.  */
 
@@ -134,7 +138,7 @@
 
 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
@@ -154,9 +158,9 @@
 
 /* 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)
     {
@@ -202,9 +206,9 @@
   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;
     }
 }
@@ -243,7 +247,7 @@
 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++)
@@ -263,7 +267,7 @@
 /* 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;
 
@@ -301,7 +305,7 @@
 {
   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))
     {
@@ -384,7 +388,7 @@
    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;
@@ -401,7 +405,7 @@
 /* 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
@@ -443,7 +447,7 @@
 /* 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
@@ -481,7 +485,7 @@
 /* Evaluates negation of IV.  */
 
 static bool
-iv_neg (struct rtx_iv *iv)
+iv_neg (class rtx_iv *iv)
 {
   if (iv->extend == IV_UNKNOWN_EXTEND)
     {
@@ -504,7 +508,7 @@
 /* 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;
@@ -574,7 +578,7 @@
 /* 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;
 
@@ -599,7 +603,7 @@
 /* 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;
 
@@ -809,9 +813,9 @@
 /* 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 ();
@@ -822,9 +826,9 @@
    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;
@@ -834,9 +838,9 @@
 }
 
 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);
@@ -849,7 +853,7 @@
    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;
@@ -927,11 +931,11 @@
 
 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;
 
@@ -1038,7 +1042,7 @@
 /* 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);
@@ -1102,7 +1106,7 @@
    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;
@@ -1163,7 +1167,7 @@
    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;
 
@@ -1188,7 +1192,7 @@
 /* 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;
 
@@ -1208,7 +1212,7 @@
 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))
@@ -1230,7 +1234,7 @@
 /* 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;
 
@@ -1380,24 +1384,23 @@
 static rtx
 find_single_def_src (unsigned int regno)
 {
-  df_ref adef;
-  rtx set, src;
-
-  for (;;)
+  rtx src = NULL_RTX;
+
+  /* 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);
@@ -1849,7 +1852,7 @@
    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;
@@ -1968,15 +1971,15 @@
 	    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))
@@ -2070,8 +2073,8 @@
    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;
 
@@ -2129,8 +2132,8 @@
    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;
@@ -2245,7 +2248,7 @@
    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;
@@ -2303,11 +2306,11 @@
    (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;
@@ -2865,7 +2868,7 @@
    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,12 +2916,12 @@
 /* Finds a simple exit of LOOP and stores its description into DESC.  */
 
 void
-find_simple_exit (struct loop *loop, struct niter_desc *desc)
+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;
 
@@ -2997,16 +3000,29 @@
 	fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
     }
 
+  /* Fix up the finiteness if possible.  We can only do it for single exit,
+     since the loop is finite, but it's possible that we predicate one loop
+     exit to be finite which can not be determined as finite in middle-end as
+     well.  It results in incorrect predicate information on the exit condition
+     expression.  For example, if says [(int) _1 + -8, + , -8] != 0 finite,
+     it means _1 can exactly divide -8.  */
+  if (desc->infinite && single_exit (loop) && finite_loop_p (loop))
+    {
+      desc->infinite = NULL_RTX;
+      if (dump_file)
+	fprintf (dump_file, "  infinite updated to finite.\n");
+    }
+
   free (body);
 }
 
 /* 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;
@@ -3023,9 +3039,9 @@
 /* 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;