IA MCU psABI support: changes to libraries
[gcc.git] / gcc / gimple-ssa-strength-reduction.c
index 6bf54d64605bd5f0493101aae02516a87378abba..1d666676c31aa434509e22f3fedf338f9b9d7243 100644 (file)
@@ -1,5 +1,5 @@
 /* Straight-line strength reduction.
-   Copyright (C) 2012-2014 Free Software Foundation, Inc.
+   Copyright (C) 2012-2015 Free Software Foundation, Inc.
    Contributed by Bill Schmidt, IBM <wschmidt@linux.ibm.com>
 
 This file is part of GCC.
@@ -36,18 +36,35 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
 #include "tree.h"
-#include "hash-map.h"
-#include "hash-table.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "tm.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.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 "gimple-iterator.h"
 #include "gimplify-me.h"
 #include "stor-layout.h"
+#include "rtl.h"
+#include "flags.h"
+#include "insn-config.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 "tree-pass.h"
 #include "cfgloop.h"
@@ -59,7 +76,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "tree-ssanames.h"
 #include "domwalk.h"
-#include "expmed.h"
 #include "params.h"
 #include "tree-ssa-address.h"
 #include "tree-affine.h"
@@ -408,23 +424,21 @@ lookup_cand (cand_idx idx)
 
 /* Helper for hashing a candidate chain header.  */
 
-struct cand_chain_hasher : typed_noop_remove <cand_chain>
+struct cand_chain_hasher : nofree_ptr_hash <cand_chain>
 {
-  typedef cand_chain value_type;
-  typedef cand_chain compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const cand_chain *);
+  static inline bool equal (const cand_chain *, const cand_chain *);
 };
 
 inline hashval_t
-cand_chain_hasher::hash (const value_type *p)
+cand_chain_hasher::hash (const cand_chain *p)
 {
   tree base_expr = p->base_expr;
   return iterative_hash_expr (base_expr, 0);
 }
 
 inline bool
-cand_chain_hasher::equal (const value_type *chain1, const compare_type *chain2)
+cand_chain_hasher::equal (const cand_chain *chain1, const cand_chain *chain2)
 {
   return operand_equal_p (chain1->base_expr, chain2->base_expr, 0);
 }
@@ -668,7 +682,7 @@ static int
 stmt_cost (gimple gs, bool speed)
 {
   tree lhs, rhs1, rhs2;
-  enum machine_mode lhs_mode;
+  machine_mode lhs_mode;
 
   gcc_assert (is_gimple_assign (gs));
   lhs = gimple_assign_lhs (gs);
@@ -694,7 +708,7 @@ stmt_cost (gimple gs, bool speed)
     case NEGATE_EXPR:
       return neg_cost (speed, lhs_mode);
 
-    case NOP_EXPR:
+    CASE_CONVERT:
       return convert_cost (lhs_mode, TYPE_MODE (TREE_TYPE (rhs1)), speed);
 
     /* Note that we don't assign costs to copies that in most cases
@@ -742,7 +756,7 @@ add_cand_for_stmt (gimple gs, slsr_cand_t c)
    is used to help find a basis for subsequent candidates.  */
 
 static void
-slsr_process_phi (gimple phi, bool speed)
+slsr_process_phi (gphi *phi, bool speed)
 {
   unsigned i;
   tree arg0_base = NULL_TREE, base_type;
@@ -982,7 +996,7 @@ slsr_process_ref (gimple gs)
 {
   tree ref_expr, base, offset, type;
   HOST_WIDE_INT bitsize, bitpos;
-  enum machine_mode mode;
+  machine_mode mode;
   int unsignedp, volatilep;
   slsr_cand_t c;
 
@@ -1476,8 +1490,8 @@ legal_cast_p_1 (tree lhs, tree rhs)
   rhs_type = TREE_TYPE (rhs);
   lhs_size = TYPE_PRECISION (lhs_type);
   rhs_size = TYPE_PRECISION (rhs_type);
-  lhs_wraps = TYPE_OVERFLOW_WRAPS (lhs_type);
-  rhs_wraps = TYPE_OVERFLOW_WRAPS (rhs_type);
+  lhs_wraps = ANY_INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS (lhs_type);
+  rhs_wraps = ANY_INTEGRAL_TYPE_P (rhs_type) && TYPE_OVERFLOW_WRAPS (rhs_type);
 
   if (lhs_size < rhs_size
       || (rhs_wraps && !lhs_wraps)
@@ -1667,12 +1681,13 @@ void
 find_candidates_dom_walker::before_dom_children (basic_block bb)
 {
   bool speed = optimize_bb_for_speed_p (bb);
-  gimple_stmt_iterator gsi;
 
-  for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-    slsr_process_phi (gsi_stmt (gsi), speed);
+  for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
+    slsr_process_phi (gsi.phi (), speed);
 
-  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+       gsi_next (&gsi))
     {
       gimple gs = gsi_stmt (gsi);
 
@@ -1704,7 +1719,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
              rhs2 = gimple_assign_rhs2 (gs);
              /* Fall-through.  */
 
-           case NOP_EXPR:
+           CASE_CONVERT:
            case MODIFY_EXPR:
            case NEGATE_EXPR:
              rhs1 = gimple_assign_rhs1 (gs);
@@ -1732,7 +1747,7 @@ find_candidates_dom_walker::before_dom_children (basic_block bb)
              slsr_process_neg (gs, rhs1, speed);
              break;
 
-           case NOP_EXPR:
+           CASE_CONVERT:
              slsr_process_cast (gs, rhs1, speed);
              break;
 
@@ -2022,7 +2037,7 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
       /* It is not useful to replace casts, copies, or adds of
         an SSA name and a constant.  */
       && cand_code != MODIFY_EXPR
-      && cand_code != NOP_EXPR
+      && !CONVERT_EXPR_CODE_P (cand_code)
       && cand_code != PLUS_EXPR
       && cand_code != POINTER_PLUS_EXPR
       && cand_code != MINUS_EXPR)
@@ -2052,7 +2067,7 @@ replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
       if (bump == 0)
        {
          tree lhs = gimple_assign_lhs (c->cand_stmt);
-         gimple copy_stmt = gimple_build_assign (lhs, basis_name);
+         gassign *copy_stmt = gimple_build_assign (lhs, basis_name);
          gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
          gimple_set_location (copy_stmt, gimple_location (c->cand_stmt));
          gsi_replace (&gsi, copy_stmt, false);
@@ -2151,7 +2166,7 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
   basic_block insert_bb;
   gimple_stmt_iterator gsi;
   tree lhs, basis_type;
-  gimple new_stmt;
+  gassign *new_stmt;
 
   /* If the add candidate along this incoming edge has the same
      index as C's hidden basis, the hidden basis represents this
@@ -2174,8 +2189,7 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
        }
 
       bump_tree = wide_int_to_tree (basis_type, bump);
-      new_stmt = gimple_build_assign_with_ops (code, lhs, basis_name,
-                                              bump_tree);
+      new_stmt = gimple_build_assign (lhs, code, basis_name, bump_tree);
     }
   else
     {
@@ -2187,15 +2201,14 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
       if (incr_vec[i].initializer)
        {
          enum tree_code code = negate_incr ? MINUS_EXPR : PLUS_EXPR;
-         new_stmt = gimple_build_assign_with_ops (code, lhs, basis_name,
-                                                  incr_vec[i].initializer);
+         new_stmt = gimple_build_assign (lhs, code, basis_name,
+                                         incr_vec[i].initializer);
        }
       else if (increment == 1)
-       new_stmt = gimple_build_assign_with_ops (PLUS_EXPR, lhs, basis_name,
-                                                c->stride);
+       new_stmt = gimple_build_assign (lhs, PLUS_EXPR, basis_name, c->stride);
       else if (increment == -1)
-       new_stmt = gimple_build_assign_with_ops (MINUS_EXPR, lhs, basis_name,
-                                                c->stride);
+       new_stmt = gimple_build_assign (lhs, MINUS_EXPR, basis_name,
+                                       c->stride);
       else
        gcc_unreachable ();
     }
@@ -2235,7 +2248,7 @@ create_phi_basis (slsr_cand_t c, gimple from_phi, tree basis_name,
 {
   int i;
   tree name, phi_arg;
-  gimple phi;
+  gphi *phi;
   vec<tree> phi_args;
   slsr_cand_t basis = lookup_cand (c->basis);
   int nargs = gimple_phi_num_args (from_phi);
@@ -2805,7 +2818,7 @@ total_savings (int repl_savings, slsr_cand_t c, const widest_int &incr,
    up sometime.  */
 
 static void
-analyze_increments (slsr_cand_t first_dep, enum machine_mode mode, bool speed)
+analyze_increments (slsr_cand_t first_dep, machine_mode mode, bool speed)
 {
   unsigned i;
 
@@ -2970,7 +2983,7 @@ ncd_for_two_cands (basic_block bb1, basic_block bb2,
    candidates, return the earliest candidate in the block in *WHERE.  */
 
 static basic_block
-ncd_with_phi (slsr_cand_t c, const widest_int &incr, gimple phi,
+ncd_with_phi (slsr_cand_t c, const widest_int &incr, gphi *phi,
              basic_block ncd, slsr_cand_t *where)
 {
   unsigned i;
@@ -2986,7 +2999,8 @@ ncd_with_phi (slsr_cand_t c, const widest_int &incr, gimple phi,
          gimple arg_def = SSA_NAME_DEF_STMT (arg);
 
          if (gimple_code (arg_def) == GIMPLE_PHI)
-           ncd = ncd_with_phi (c, incr, arg_def, ncd, where);
+           ncd = ncd_with_phi (c, incr, as_a <gphi *> (arg_def), ncd,
+                               where);
          else 
            {
              slsr_cand_t arg_cand = base_cand_from_table (arg);
@@ -3020,7 +3034,8 @@ ncd_of_cand_and_phis (slsr_cand_t c, const widest_int &incr, slsr_cand_t *where)
     }
   
   if (phi_dependent_cand_p (c))
-    ncd = ncd_with_phi (c, incr, lookup_cand (c->def_phi)->cand_stmt,
+    ncd = ncd_with_phi (c, incr,
+                       as_a <gphi *> (lookup_cand (c->def_phi)->cand_stmt),
                        ncd, where);
 
   return ncd;
@@ -3108,7 +3123,7 @@ insert_initializers (slsr_cand_t c)
     {
       basic_block bb;
       slsr_cand_t where = NULL;
-      gimple init_stmt;
+      gassign *init_stmt;
       tree stride_type, new_name, incr_tree;
       widest_int incr = incr_vec[i].incr;
 
@@ -3146,8 +3161,8 @@ insert_initializers (slsr_cand_t c)
       /* Create the initializer and insert it in the latest possible
         dominating position.  */
       incr_tree = wide_int_to_tree (stride_type, incr);
-      init_stmt = gimple_build_assign_with_ops (MULT_EXPR, new_name,
-                                               c->stride, incr_tree);
+      init_stmt = gimple_build_assign (new_name, MULT_EXPR,
+                                      c->stride, incr_tree);
       if (where)
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (where->cand_stmt);
@@ -3246,12 +3261,11 @@ static tree
 introduce_cast_before_cand (slsr_cand_t c, tree to_type, tree from_expr)
 {
   tree cast_lhs;
-  gimple cast_stmt;
+  gassign *cast_stmt;
   gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
 
   cast_lhs = make_temp_ssa_name (to_type, NULL, "slsr");
-  cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, cast_lhs,
-                                           from_expr, NULL_TREE);
+  cast_stmt = gimple_build_assign (cast_lhs, NOP_EXPR, from_expr);
   gimple_set_location (cast_stmt, gimple_location (c->cand_stmt));
   gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
 
@@ -3408,7 +3422,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
       
       if (types_compatible_p (lhs_type, basis_type))
        {
-         gimple copy_stmt = gimple_build_assign (lhs, basis_name);
+         gassign *copy_stmt = gimple_build_assign (lhs, basis_name);
          gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
          gimple_set_location (copy_stmt, gimple_location (c->cand_stmt));
          gsi_replace (&gsi, copy_stmt, false);
@@ -3420,9 +3434,7 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
       else
        {
          gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
-         gimple cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, lhs,
-                                                          basis_name,
-                                                          NULL_TREE);
+         gassign *cast_stmt = gimple_build_assign (lhs, NOP_EXPR, basis_name);
          gimple_set_location (cast_stmt, gimple_location (c->cand_stmt));
          gsi_replace (&gsi, cast_stmt, false);
          c->cand_stmt = cast_stmt;
@@ -3461,7 +3473,7 @@ replace_profitable_candidates (slsr_cand_t c)
       if (i >= 0
          && profitable_increment_p (i) 
          && orig_code != MODIFY_EXPR
-         && orig_code != NOP_EXPR)
+         && !CONVERT_EXPR_CODE_P (orig_code))
        {
          if (phi_dependent_cand_p (c))
            {
@@ -3549,7 +3561,7 @@ analyze_candidates_and_replace (void)
         less expensive to calculate than the replaced statements.  */
       else
        {
-         enum machine_mode mode;
+         machine_mode mode;
          bool speed;
 
          /* Determine whether we'll be generating pointer arithmetic