PR c++/68795: fix uninitialized close_paren_loc in cp_parser_postfix_expression
[gcc.git] / gcc / gcse.c
index 4be3f36a773a0c9288d140e5d53e3dd6c49b7425..500de7a95ce856d7cd710d3be1efed865d40703c 100644 (file)
@@ -1,5 +1,5 @@
 /* Partial redundancy elimination / Hoisting for RTL.
-   Copyright (C) 1997-2015 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -135,59 +135,27 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
-#include "toplev.h"
-#include "hard-reg-set.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
-#include "hash-set.h"
-#include "machmode.h"
-#include "vec.h"
-#include "double-int.h"
-#include "input.h"
-#include "alias.h"
-#include "symtab.h"
-#include "wide-int.h"
-#include "inchash.h"
 #include "tree.h"
+#include "predict.h"
+#include "df.h"
 #include "tm_p.h"
+#include "insn-config.h"
 #include "regs.h"
 #include "ira.h"
-#include "flags.h"
-#include "insn-config.h"
 #include "recog.h"
-#include "predict.h"
-#include "function.h"
-#include "dominance.h"
-#include "cfg.h"
+#include "diagnostic-core.h"
 #include "cfgrtl.h"
 #include "cfganal.h"
 #include "lcm.h"
 #include "cfgcleanup.h"
-#include "basic-block.h"
-#include "hashtab.h"
-#include "statistics.h"
-#include "real.h"
-#include "fixed-value.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
 #include "expr.h"
-#include "except.h"
-#include "ggc.h"
 #include "params.h"
-#include "cselib.h"
 #include "intl.h"
-#include "obstack.h"
 #include "tree-pass.h"
-#include "hash-table.h"
-#include "df.h"
 #include "dbgcnt.h"
-#include "target.h"
 #include "gcse.h"
 #include "gcse-common.h"
 
@@ -386,9 +354,8 @@ struct ls_expr
 /* Head of the list of load/store memory refs.  */
 static struct ls_expr * pre_ldst_mems = NULL;
 
-struct pre_ldst_expr_hasher : typed_noop_remove <ls_expr>
+struct pre_ldst_expr_hasher : nofree_ptr_hash <ls_expr>
 {
-  typedef ls_expr *value_type;
   typedef value_type compare_type;
   static inline hashval_t hash (const ls_expr *);
   static inline bool equal (const ls_expr *, const ls_expr *);
@@ -486,14 +453,13 @@ static void hash_scan_insn (rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_set (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_clobber (rtx, rtx_insn *, struct gcse_hash_table_d *);
 static void hash_scan_call (rtx, rtx_insn *, struct gcse_hash_table_d *);
-static int want_to_gcse_p (rtx, int *);
 static int oprs_unchanged_p (const_rtx, const rtx_insn *, int);
 static int oprs_anticipatable_p (const_rtx, const rtx_insn *);
 static int oprs_available_p (const_rtx, const rtx_insn *);
 static void insert_expr_in_table (rtx, machine_mode, rtx_insn *, int, int,
                                  int, struct gcse_hash_table_d *);
 static unsigned int hash_expr (const_rtx, machine_mode, int *, int);
-static void record_last_reg_set_info (rtx, int);
+static void record_last_reg_set_info (rtx_insn *, int);
 static void record_last_mem_set_info (rtx_insn *);
 static void record_last_set_info (rtx, const_rtx, void *);
 static void compute_hash_table (struct gcse_hash_table_d *);
@@ -516,7 +482,7 @@ static void pre_insert_copies (void);
 static int pre_delete (void);
 static int pre_gcse (struct edge_list *);
 static int one_pre_gcse_pass (void);
-static void add_label_notes (rtx, rtx);
+static void add_label_notes (rtx, rtx_insn *);
 static void alloc_code_hoist_mem (int, int);
 static void free_code_hoist_mem (void);
 static void compute_code_hoist_vbeinout (void);
@@ -544,8 +510,6 @@ static void trim_ld_motion_mems (void);
 static void update_ld_motion_stores (struct gcse_expr *);
 static void clear_modify_mem_tables (void);
 static void free_modify_mem_tables (void);
-static rtx gcse_emit_move_after (rtx, rtx, rtx_insn *);
-static bool is_too_expensive (const char *);
 
 #define GNEW(T)                        ((T *) gmalloc (sizeof (T)))
 #define GCNEW(T)               ((T *) gcalloc (1, sizeof (T)))
@@ -573,7 +537,8 @@ compute_can_copy (void)
 {
   int i;
 #ifndef AVOID_CCMODE_COPIES
-  rtx reg, insn;
+  rtx reg;
+ rtx_insn *insn;
 #endif
   memset (can_copy, 0, NUM_MACHINE_MODES);
 
@@ -585,7 +550,7 @@ compute_can_copy (void)
        can_copy[i] = 0;
 #else
        reg = gen_rtx_REG ((machine_mode) i, LAST_VIRTUAL_REGISTER + 1);
-       insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg));
+       insn = emit_insn (gen_rtx_SET (reg, reg));
        if (recog (PATTERN (insn), insn, NULL) >= 0)
          can_copy[i] = 1;
 #endif
@@ -777,7 +742,7 @@ static basic_block current_bb;
    GCSE.  */
 
 static int
-want_to_gcse_p (rtx x, int *max_distance_ptr)
+want_to_gcse_p (rtx x, machine_mode mode, int *max_distance_ptr)
 {
 #ifdef STACK_REGS
   /* On register stack architectures, don't GCSE constants from the
@@ -828,7 +793,7 @@ want_to_gcse_p (rtx x, int *max_distance_ptr)
 
          gcc_assert (!optimize_function_for_speed_p (cfun)
                      && optimize_function_for_size_p (cfun));
-         cost = set_src_cost (x, 0);
+         cost = set_src_cost (x, mode, 0);
 
          if (cost < COSTS_N_INSNS (GCSE_UNRESTRICTED_COST))
            {
@@ -883,8 +848,7 @@ can_assign_to_reg_without_clobbers_p (rtx x)
   if (test_insn == 0)
     {
       test_insn
-       = make_insn_raw (gen_rtx_SET (VOIDmode,
-                                     gen_rtx_REG (word_mode,
+       = make_insn_raw (gen_rtx_SET (gen_rtx_REG (word_mode,
                                                   FIRST_PSEUDO_REGISTER * 2),
                                      const0_rtx));
       SET_NEXT_INSN (test_insn) = SET_PREV_INSN (test_insn) = 0;
@@ -1286,8 +1250,8 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
       if (note != 0
          && REG_NOTE_KIND (note) == REG_EQUAL
          && !REG_P (src)
-         && want_to_gcse_p (XEXP (note, 0), NULL))
-       src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src);
+         && want_to_gcse_p (XEXP (note, 0), GET_MODE (dest), NULL))
+       src = XEXP (note, 0), set = gen_rtx_SET (dest, src);
 
       /* Only record sets of pseudo-regs in the hash table.  */
       if (regno >= FIRST_PSEUDO_REGISTER
@@ -1300,7 +1264,7 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
             can't do the same thing at the rtl level.  */
          && !can_throw_internal (insn)
          /* Is SET_SRC something we want to gcse?  */
-         && want_to_gcse_p (src, &max_distance)
+         && want_to_gcse_p (src, GET_MODE (dest), &max_distance)
          /* Don't CSE a nop.  */
          && ! set_noop_p (set)
          /* Don't GCSE if it has attached REG_EQUIV note.
@@ -1332,43 +1296,42 @@ hash_scan_set (rtx set, rtx_insn *insn, struct gcse_hash_table_d *table)
      the REG stored in that memory. This makes it possible to remove
      redundant loads from due to stores to the same location.  */
   else if (flag_gcse_las && REG_P (src) && MEM_P (dest))
-      {
-        unsigned int regno = REGNO (src);
-       int max_distance = 0;
-
-       /* Only record sets of pseudo-regs in the hash table.  */
-        if (regno >= FIRST_PSEUDO_REGISTER
-          /* Don't GCSE something if we can't do a reg/reg copy.  */
-          && can_copy_p (GET_MODE (src))
-          /* GCSE commonly inserts instruction after the insn.  We can't
-             do that easily for EH edges so disable GCSE on these for now.  */
-          && !can_throw_internal (insn)
-          /* Is SET_DEST something we want to gcse?  */
-          && want_to_gcse_p (dest, &max_distance)
-          /* Don't CSE a nop.  */
-          && ! set_noop_p (set)
-          /* Don't GCSE if it has attached REG_EQUIV note.
-             At this point this only function parameters should have
-             REG_EQUIV notes and if the argument slot is used somewhere
-             explicitly, it means address of parameter has been taken,
-             so we should not extend the lifetime of the pseudo.  */
-          && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
-              || ! MEM_P (XEXP (note, 0))))
-             {
-               /* Stores are never anticipatable.  */
-               int antic_p = 0;
-              /* An expression is not available if its operands are
-                 subsequently modified, including this insn.  It's also not
-                 available if this is a branch, because we can't insert
-                 a set after the branch.  */
-               int avail_p = oprs_available_p (dest, insn)
-                            && ! JUMP_P (insn);
-
-              /* Record the memory expression (DEST) in the hash table.  */
-              insert_expr_in_table (dest, GET_MODE (dest), insn,
-                                    antic_p, avail_p, max_distance, table);
-             }
-      }
+    {
+      unsigned int regno = REGNO (src);
+      int max_distance = 0;
+
+      /* Only record sets of pseudo-regs in the hash table.  */
+      if (regno >= FIRST_PSEUDO_REGISTER
+         /* Don't GCSE something if we can't do a reg/reg copy.  */
+         && can_copy_p (GET_MODE (src))
+         /* GCSE commonly inserts instruction after the insn.  We can't
+            do that easily for EH edges so disable GCSE on these for now.  */
+         && !can_throw_internal (insn)
+         /* Is SET_DEST something we want to gcse?  */
+         && want_to_gcse_p (dest, GET_MODE (dest), &max_distance)
+         /* Don't CSE a nop.  */
+         && ! set_noop_p (set)
+         /* Don't GCSE if it has attached REG_EQUIV note.
+            At this point this only function parameters should have
+            REG_EQUIV notes and if the argument slot is used somewhere
+            explicitly, it means address of parameter has been taken,
+            so we should not extend the lifetime of the pseudo.  */
+         && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0
+             || ! MEM_P (XEXP (note, 0))))
+       {
+         /* Stores are never anticipatable.  */
+         int antic_p = 0;
+         /* An expression is not available if its operands are
+            subsequently modified, including this insn.  It's also not
+            available if this is a branch, because we can't insert
+            a set after the branch.  */
+         int avail_p = oprs_available_p (dest, insn) && ! JUMP_P (insn);
+
+         /* Record the memory expression (DEST) in the hash table.  */
+         insert_expr_in_table (dest, GET_MODE (dest), insn,
+                               antic_p, avail_p, max_distance, table);
+       }
+    }
 }
 
 static void
@@ -1471,7 +1434,7 @@ dump_hash_table (FILE *file, const char *name, struct gcse_hash_table_d *table)
    valid, as a quick test to invalidate them.  */
 
 static void
-record_last_reg_set_info (rtx insn, int regno)
+record_last_reg_set_info (rtx_insn *insn, int regno)
 {
   struct reg_avail_info *info = &reg_avail_info[regno];
   int luid = DF_INSN_LUID (insn);
@@ -2007,7 +1970,7 @@ process_insert_insn (struct gcse_expr *expr)
      insn will be recognized (this also adds any needed CLOBBERs).  */
   else
     {
-      rtx_insn *insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp));
+      rtx_insn *insn = emit_insn (gen_rtx_SET (reg, exp));
 
       if (insn_invalid_p (insn, false))
        gcc_unreachable ();
@@ -2048,21 +2011,23 @@ insert_insn_end_basic_block (struct gcse_expr *expr, basic_block bb)
          && (!single_succ_p (bb)
              || single_succ_edge (bb)->flags & EDGE_ABNORMAL)))
     {
-#ifdef HAVE_cc0
       /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts
         if cc0 isn't set.  */
-      rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
-      if (note)
-       insn = safe_as_a <rtx_insn *> (XEXP (note, 0));
-      else
+      if (HAVE_cc0)
        {
-         rtx_insn *maybe_cc0_setter = prev_nonnote_insn (insn);
-         if (maybe_cc0_setter
-             && INSN_P (maybe_cc0_setter)
-             && sets_cc0_p (PATTERN (maybe_cc0_setter)))
-           insn = maybe_cc0_setter;
+         rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
+         if (note)
+           insn = safe_as_a <rtx_insn *> (XEXP (note, 0));
+         else
+           {
+             rtx_insn *maybe_cc0_setter = prev_nonnote_insn (insn);
+             if (maybe_cc0_setter
+                 && INSN_P (maybe_cc0_setter)
+                 && sets_cc0_p (PATTERN (maybe_cc0_setter)))
+               insn = maybe_cc0_setter;
+           }
        }
-#endif
+
       /* FIXME: What if something in cc0/jump uses value set in new insn?  */
       new_insn = emit_insn_before_noloc (pat, insn, bb);
     }
@@ -2227,7 +2192,8 @@ pre_insert_copy_insn (struct gcse_expr *expr, rtx_insn *insn)
   int regno = REGNO (reg);
   int indx = expr->bitmap_index;
   rtx pat = PATTERN (insn);
-  rtx set, first_set, new_insn;
+  rtx set, first_set;
+  rtx_insn *new_insn;
   rtx old_reg;
   int i;
 
@@ -2435,7 +2401,7 @@ single_set_gcse (rtx_insn *insn)
 /* Emit move from SRC to DEST noting the equivalence with expression computed
    in INSN.  */
 
-static rtx
+static rtx_insn *
 gcse_emit_move_after (rtx dest, rtx src, rtx_insn *insn)
 {
   rtx_insn *new_rtx;
@@ -2598,7 +2564,7 @@ one_pre_gcse_pass (void)
 
   /* Return if there's nothing to do, or it is too expensive.  */
   if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1
-      || is_too_expensive (_("PRE disabled")))
+      || gcse_or_cprop_is_too_expensive (_("PRE disabled")))
     return 0;
 
   /* We need alias.  */
@@ -2663,7 +2629,7 @@ one_pre_gcse_pass (void)
    necessary REG_LABEL_OPERAND and REG_LABEL_TARGET notes.  */
 
 static void
-add_label_notes (rtx x, rtx insn)
+add_label_notes (rtx x, rtx_insn *insn)
 {
   enum rtx_code code = GET_CODE (x);
   int i, j;
@@ -3526,7 +3492,7 @@ one_code_hoisting_pass (void)
 
   /* Return if there's nothing to do, or it is too expensive.  */
   if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1
-      || is_too_expensive (_("GCSE disabled")))
+      || gcse_or_cprop_is_too_expensive (_("GCSE disabled")))
     return 0;
 
   doing_code_hoisting_p = true;
@@ -3961,7 +3927,6 @@ update_ld_motion_stores (struct gcse_expr * expr)
          rtx pat = PATTERN (insn);
          rtx src = SET_SRC (pat);
          rtx reg = expr->reaching_reg;
-         rtx copy;
 
          /* If we've already copied it, continue.  */
          if (expr->reaching_reg == src)
@@ -3976,7 +3941,7 @@ update_ld_motion_stores (struct gcse_expr * expr)
              fprintf (dump_file, "\n");
            }
 
-         copy = gen_move_insn (reg, copy_rtx (SET_SRC (pat)));
+         rtx_insn *copy = gen_move_insn (reg, copy_rtx (SET_SRC (pat)));
          emit_insn_before (copy, insn);
          SET_SRC (pat) = reg;
          df_insn_rescan (insn);
@@ -3991,9 +3956,13 @@ update_ld_motion_stores (struct gcse_expr * expr)
 /* Return true if the graph is too expensive to optimize. PASS is the
    optimization about to be performed.  */
 
-static bool
-is_too_expensive (const char *pass)
+bool
+gcse_or_cprop_is_too_expensive (const char *pass)
 {
+  unsigned int memory_request = (n_basic_blocks_for_fn (cfun)
+                                * SBITMAP_SET_SIZE (max_reg_num ())
+                                * sizeof (SBITMAP_ELT_TYPE));
+  
   /* Trying to perform global optimizations on flow graphs which have
      a high connectivity will take a long time and is unlikely to be
      particularly useful.
@@ -4015,13 +3984,12 @@ is_too_expensive (const char *pass)
 
   /* If allocating memory for the dataflow bitmaps would take up too much
      storage it's better just to disable the optimization.  */
-  if ((n_basic_blocks_for_fn (cfun)
-       * SBITMAP_SET_SIZE (max_reg_num ())
-       * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
+  if (memory_request > MAX_GCSE_MEMORY)
     {
       warning (OPT_Wdisabled_optimization,
-              "%s: %d basic blocks and %d registers",
-              pass, n_basic_blocks_for_fn (cfun), max_reg_num ());
+              "%s: %d basic blocks and %d registers; increase --param max-gcse-memory above %d",
+              pass, n_basic_blocks_for_fn (cfun), max_reg_num (),
+              memory_request);
 
       return true;
     }