ipa-cp.c (ipcp_cloning_candidate_p): Use opt_for_fn.
[gcc.git] / gcc / tree-cfg.c
index bdd309a62f6700189dcd42abd562cba1894c3517..9dd8961cb8f9421fe1ef7e4710835506c5c0cd55 100644 (file)
@@ -29,9 +29,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "stor-layout.h"
 #include "print-tree.h"
 #include "tm_p.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
 #include "basic-block.h"
 #include "flags.h"
-#include "function.h"
 #include "gimple-pretty-print.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
@@ -44,6 +54,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "gimple-walk.h"
 #include "gimple-ssa.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
 #include "cgraph.h"
 #include "tree-cfg.h"
 #include "tree-phinodes.h"
@@ -253,13 +265,56 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus = NULL;
 }
 
+/* Look for ANNOTATE calls with loop annotation kind in BB; if found, remove
+   them and propagate the information to LOOP.  We assume that the annotations
+   come immediately before the condition in BB, if any.  */
+
+static void
+replace_loop_annotate_in_block (basic_block bb, struct loop *loop)
+{
+  gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  gimple stmt = gsi_stmt (gsi);
+
+  if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
+    return;
+
+  for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
+    {
+      stmt = gsi_stmt (gsi);
+      if (gimple_code (stmt) != GIMPLE_CALL)
+       break;
+      if (!gimple_call_internal_p (stmt)
+         || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+       break;
+
+      switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
+       {
+       case annot_expr_ivdep_kind:
+         loop->safelen = INT_MAX;
+         break;
+       case annot_expr_no_vector_kind:
+         loop->dont_vectorize = true;
+         break;
+       case annot_expr_vector_kind:
+         loop->force_vectorize = true;
+         cfun->has_force_vectorize_loops = true;
+         break;
+       default:
+         gcc_unreachable ();
+       }
+
+      stmt = gimple_build_assign (gimple_call_lhs (stmt),
+                                 gimple_call_arg (stmt, 0));
+      gsi_replace (&gsi, stmt, true);
+    }
+}
 
 /* Look for ANNOTATE calls with loop annotation kind; if found, remove
    them and propagate the information to the loop.  We assume that the
    annotations come immediately before the condition of the loop.  */
 
 static void
-replace_loop_annotate ()
+replace_loop_annotate (void)
 {
   struct loop *loop;
   basic_block bb;
@@ -268,37 +323,12 @@ replace_loop_annotate ()
 
   FOR_EACH_LOOP (loop, 0)
     {
-      gsi = gsi_last_bb (loop->header);
-      stmt = gsi_stmt (gsi);
-      if (!(stmt && gimple_code (stmt) == GIMPLE_COND))
-       continue;
-      for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi))
-       {
-         stmt = gsi_stmt (gsi);
-         if (gimple_code (stmt) != GIMPLE_CALL)
-           break;
-         if (!gimple_call_internal_p (stmt)
-             || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-           break;
-         switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
-           {
-           case annot_expr_ivdep_kind:
-             loop->safelen = INT_MAX;
-             break;
-           case annot_expr_no_vector_kind:
-             loop->dont_vectorize = true;
-             break;
-           case annot_expr_vector_kind:
-             loop->force_vectorize = true;
-             cfun->has_force_vectorize_loops = true;
-             break;
-           default:
-             gcc_unreachable ();
-           }
-         stmt = gimple_build_assign (gimple_call_lhs (stmt),
-                                     gimple_call_arg (stmt, 0));
-         gsi_replace (&gsi, stmt, true);
-       }
+      /* First look into the header.  */
+      replace_loop_annotate_in_block (loop->header, loop);
+
+      /* Then look into the latch, if any.  */
+      if (loop->latch)
+       replace_loop_annotate_in_block (loop->latch, loop);
     }
 
   /* Remove IFN_ANNOTATE.  Safeguard for the case loop->latch == NULL.  */
@@ -308,10 +338,11 @@ replace_loop_annotate ()
        {
          stmt = gsi_stmt (gsi);
          if (gimple_code (stmt) != GIMPLE_CALL)
-           break;
+           continue;
          if (!gimple_call_internal_p (stmt)
              || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
-           break;
+           continue;
+
          switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)))
            {
            case annot_expr_ivdep_kind:
@@ -321,6 +352,7 @@ replace_loop_annotate ()
            default:
              gcc_unreachable ();
            }
+
          warning_at (gimple_location (stmt), 0, "ignoring loop annotation");
          stmt = gimple_build_assign (gimple_call_lhs (stmt),
                                      gimple_call_arg (stmt, 0));
@@ -1674,8 +1706,12 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
        return false;
     }
 
-  /* Protect the loop latches.  */
-  if (current_loops && b->loop_father->latch == b)
+  /* Protect simple loop latches.  We only want to avoid merging
+     the latch with the loop header in this case.  */
+  if (current_loops
+      && b->loop_father->latch == b
+      && loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES)
+      && b->loop_father->header == a)
     return false;
 
   /* It must be possible to eliminate all phi nodes in B.  If ssa form
@@ -3539,12 +3575,21 @@ verify_gimple_assign_unary (gimple stmt)
 
         return false;
       }
-
-    case VEC_UNPACK_HI_EXPR:
-    case VEC_UNPACK_LO_EXPR:
     case REDUC_MAX_EXPR:
     case REDUC_MIN_EXPR:
     case REDUC_PLUS_EXPR:
+      if (!VECTOR_TYPE_P (rhs1_type)
+         || !useless_type_conversion_p (lhs_type, TREE_TYPE (rhs1_type)))
+        {
+         error ("reduction should convert from vector to element type");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         return true;
+       }
+      return false;
+
+    case VEC_UNPACK_HI_EXPR:
+    case VEC_UNPACK_LO_EXPR:
     case VEC_UNPACK_FLOAT_HI_EXPR:
     case VEC_UNPACK_FLOAT_LO_EXPR:
       /* FIXME.  */
@@ -3554,7 +3599,6 @@ verify_gimple_assign_unary (gimple stmt)
     case ABS_EXPR:
     case BIT_NOT_EXPR:
     case PAREN_EXPR:
-    case NON_LVALUE_EXPR:
     case CONJ_EXPR:
       break;
 
@@ -3651,39 +3695,6 @@ verify_gimple_assign_binary (gimple stmt)
        return false;
       }
 
-    case VEC_LSHIFT_EXPR:
-    case VEC_RSHIFT_EXPR:
-      {
-       if (TREE_CODE (rhs1_type) != VECTOR_TYPE
-           || !(INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
-                || POINTER_TYPE_P (TREE_TYPE (rhs1_type))
-                || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1_type))
-                || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type)))
-           || (!INTEGRAL_TYPE_P (rhs2_type)
-               && (TREE_CODE (rhs2_type) != VECTOR_TYPE
-                   || !INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))))
-           || !useless_type_conversion_p (lhs_type, rhs1_type))
-         {
-           error ("type mismatch in vector shift expression");
-           debug_generic_expr (lhs_type);
-           debug_generic_expr (rhs1_type);
-           debug_generic_expr (rhs2_type);
-           return true;
-         }
-       /* For shifting a vector of non-integral components we
-          only allow shifting by a constant multiple of the element size.  */
-       if (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
-           && (TREE_CODE (rhs2) != INTEGER_CST
-               || !div_if_zero_remainder (rhs2,
-                                          TYPE_SIZE (TREE_TYPE (rhs1_type)))))
-         {
-           error ("non-element sized vector shift of floating point vector");
-           return true;
-         }
-
-       return false;
-      }
-
     case WIDEN_LSHIFT_EXPR:
       {
         if (!INTEGRAL_TYPE_P (lhs_type)
@@ -4208,8 +4219,20 @@ verify_gimple_assign_single (gimple stmt)
                  debug_generic_stmt (rhs1);
                  return true;
                }
+             if (!is_gimple_val (elt_v))
+               {
+                 error ("vector CONSTRUCTOR element is not a GIMPLE value");
+                 debug_generic_stmt (rhs1);
+                 return true;
+               }
            }
        }
+      else if (CONSTRUCTOR_NELTS (rhs1) != 0)
+       {
+         error ("non-vector CONSTRUCTOR with elements");
+         debug_generic_stmt (rhs1);
+         return true;
+       }
       return res;
     case OBJ_TYPE_REF:
     case ASSERT_EXPR:
@@ -4724,19 +4747,17 @@ verify_node_sharing (tree *tp, int *walk_subtrees, void *data)
 }
 
 static bool eh_error_found;
-static int
-verify_eh_throw_stmt_node (void **slot, void *data)
+bool
+verify_eh_throw_stmt_node (const gimple &stmt, const int &,
+                          hash_set<gimple> *visited)
 {
-  struct throw_stmt_node *node = (struct throw_stmt_node *)*slot;
-  hash_set<void *> *visited = (hash_set<void *> *) data;
-
-  if (!visited->contains (node->stmt))
+  if (!visited->contains (stmt))
     {
       error ("dead STMT in EH table");
-      debug_gimple_stmt (node->stmt);
+      debug_gimple_stmt (stmt);
       eh_error_found = true;
     }
-  return 1;
+  return true;
 }
 
 /* Verify if the location LOCs block is in BLOCKS.  */
@@ -4997,10 +5018,10 @@ verify_gimple_in_cfg (struct function *fn, bool verify_nothrow)
     }
 
   eh_error_found = false;
-  if (get_eh_throw_stmt_table (cfun))
-    htab_traverse (get_eh_throw_stmt_table (cfun),
-                  verify_eh_throw_stmt_node,
-                  &visited_stmts);
+  hash_map<gimple, int> *eh_table = get_eh_throw_stmt_table (cfun);
+  if (eh_table)
+    eh_table->traverse<hash_set<gimple> *, verify_eh_throw_stmt_node>
+      (&visited_stmts);
 
   if (err || eh_error_found)
     internal_error ("verify_gimple failed");
@@ -6971,11 +6992,12 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
       if (loops_for_fn (saved_cfun)->exits)
        FOR_EACH_EDGE (e, ei, bb->succs)
          {
-           void **slot = htab_find_slot_with_hash
-               (loops_for_fn (saved_cfun)->exits, e,
-                htab_hash_pointer (e), NO_INSERT);
+           struct loops *l = loops_for_fn (saved_cfun);
+           loop_exit **slot
+             = l->exits->find_slot_with_hash (e, htab_hash_pointer (e),
+                                              NO_INSERT);
            if (slot)
-             htab_clear_slot (loops_for_fn (saved_cfun)->exits, slot);
+             l->exits->clear_slot (slot);
          }
     }
 
@@ -8156,6 +8178,46 @@ make_pass_split_crit_edges (gcc::context *ctxt)
 }
 
 
+/* Insert COND expression which is GIMPLE_COND after STMT
+   in basic block BB with appropriate basic block split
+   and creation of a new conditionally executed basic block.
+   Return created basic block.  */
+basic_block
+insert_cond_bb (basic_block bb, gimple stmt, gimple cond)
+{
+  edge fall = split_block (bb, stmt);
+  gimple_stmt_iterator iter = gsi_last_bb (bb);
+  basic_block new_bb;
+
+  /* Insert cond statement.  */
+  gcc_assert (gimple_code (cond) == GIMPLE_COND);
+  if (gsi_end_p (iter))
+    gsi_insert_before (&iter, cond, GSI_CONTINUE_LINKING);
+  else
+    gsi_insert_after (&iter, cond, GSI_CONTINUE_LINKING);
+
+  /* Create conditionally executed block.  */
+  new_bb = create_empty_bb (bb);
+  make_edge (bb, new_bb, EDGE_TRUE_VALUE);
+  make_single_succ_edge (new_bb, fall->dest, EDGE_FALLTHRU);
+
+  /* Fix edge for split bb.  */
+  fall->flags = EDGE_FALSE_VALUE;
+
+  /* Update dominance info.  */
+  if (dom_info_available_p (CDI_DOMINATORS))
+    {
+      set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
+      set_immediate_dominator (CDI_DOMINATORS, fall->dest, bb);
+    }
+
+  /* Update loop info.  */
+  if (current_loops)
+    add_bb_to_loop (new_bb, bb->loop_father);
+
+  return new_bb;
+}
+
 /* Build a ternary operation and gimplify it.  Emit code before GSI.
    Return the gimple_val holding the result.  */