OSDN Git Service

2010-04-07 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 2010 15:31:37 +0000 (15:31 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 05:17:29 +0000 (14:17 +0900)
* ipa-reference.c (mark_load): Use get_base_address.
(mark_store): Likewise.

* tree-ssa-ccp.c (gimplify_and_update_call_from_tree): Avoid
inserting GIMPLE_NOPs into the IL.
* tree-ssa-structalias.c (get_constraint_for_component_ref):
Explicitly strip handled components and indirect references.

* fold-const.c (fold_unary_loc): Do not strip qualifiers when
folding address expressions.
* gimple.c (gimple_ior_addresses_taken_1): Use get_base_address.
* tree-ssa-alias.c (decl_refs_may_alias_p): Do not use
operand_equal_p to compare decls.
(ptr_deref_may_alias_decl_p): Likewise.
* tree-ssa-operands.c (get_asm_expr_operands): Simplify
* tree-ssa-forwprop.c (forward_propagate_into_gimple_cond):
Handle reversed comparison ops.
* tree-sra.c (asm_visit_addr): Use get_base_address.
* ipa-prop.c (visit_store_addr_for_mod_analysis): Use
get_base_address.
* ipa-reference.c (mark_address): Use get_base_address.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158069 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ipa-reference.c
gcc/tree-ssa-ccp.c

index 9b8e5b9..2900046 100644 (file)
@@ -1,5 +1,29 @@
 2010-04-07  Richard Guenther  <rguenther@suse.de>
 
+       * ipa-reference.c (mark_load): Use get_base_address.
+       (mark_store): Likewise.
+
+       * tree-ssa-ccp.c (gimplify_and_update_call_from_tree): Avoid
+       inserting GIMPLE_NOPs into the IL.
+       * tree-ssa-structalias.c (get_constraint_for_component_ref):
+       Explicitly strip handled components and indirect references.
+  
+       * fold-const.c (fold_unary_loc): Do not strip qualifiers when
+       folding address expressions.
+       * gimple.c (gimple_ior_addresses_taken_1): Use get_base_address.
+       * tree-ssa-alias.c (decl_refs_may_alias_p): Do not use
+       operand_equal_p to compare decls.
+       (ptr_deref_may_alias_decl_p): Likewise.
+       * tree-ssa-operands.c (get_asm_expr_operands): Simplify
+       * tree-ssa-forwprop.c (forward_propagate_into_gimple_cond):
+       Handle reversed comparison ops.
+       * tree-sra.c (asm_visit_addr): Use get_base_address.
+       * ipa-prop.c (visit_store_addr_for_mod_analysis): Use
+       get_base_address.
+       * ipa-reference.c (mark_address): Use get_base_address.
+
+2010-04-07  Richard Guenther  <rguenther@suse.de>
+
        * tree-ssa-forwprop.c (forward_propagate_addr_expr):
        Propagate constants everywhere.
 
index a66e627..f1946d8 100644 (file)
@@ -280,6 +280,171 @@ is_proper_for_analysis (tree t)
   return true;
 }
 
+/* Mark tree T as having address taken.  */
+
+static void
+mark_address_taken (tree x)
+{
+  if (TREE_CODE (x) == VAR_DECL
+      && module_statics_escape && has_proper_scope_for_analysis (x))
+    bitmap_set_bit (module_statics_escape, DECL_UID (x));
+}
+
+/* Wrapper around mark_address_taken for the stmt walker.  */
+
+static bool
+mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
+             void *data ATTRIBUTE_UNUSED)
+{
+  addr = get_base_address (addr);
+  if (addr)
+    mark_address_taken (addr);
+  return false;
+}
+
+/* Mark load of T.  */
+
+static bool
+mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+{
+  ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
+  t = get_base_address (t);
+  if (t && TREE_CODE (t) == VAR_DECL
+      && has_proper_scope_for_analysis (t))
+    bitmap_set_bit (local->statics_read, DECL_UID (t));
+  return false;
+}
+
+/* Mark store of T.  */
+
+static bool
+mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
+{
+  ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
+  t = get_base_address (t);
+  if (t && TREE_CODE (t) == VAR_DECL
+      && has_proper_scope_for_analysis (t))
+    {
+      if (local)
+       bitmap_set_bit (local->statics_written, DECL_UID (t));
+      /* Mark the write so we can tell which statics are
+        readonly.  */
+      if (module_statics_written)
+       bitmap_set_bit (module_statics_written, DECL_UID (t));
+    }
+  return false;
+}
+
+/* Look for memory clobber and set read_all/write_all if present.  */
+
+static void
+check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt)
+{
+  size_t i;
+  tree op;
+
+  for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
+    {
+      op = gimple_asm_clobber_op (stmt, i);
+      if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
+       {
+         /* Abandon all hope, ye who enter here. */
+         local->calls_read_all = true;
+         local->calls_write_all = true;
+       }
+    }
+}
+
+/* Look for external calls and set read_all/write_all correspondingly.  */
+
+static void
+check_call (ipa_reference_local_vars_info_t local, gimple stmt)
+{
+  int flags = gimple_call_flags (stmt);
+  tree callee_t = gimple_call_fndecl (stmt);
+
+  /* Process indirect calls.  All direct calles are handled at propagation
+     time.  */
+  if (!callee_t)
+    {
+      if (flags & ECF_CONST)
+       ;
+      else if (flags & ECF_PURE)
+       local->calls_read_all = true;
+      else
+       {
+         local->calls_read_all = true;
+         /* When function does not reutrn, it is safe to ignore anythign it writes
+            to, because the effect will never happen.  */
+         if ((flags & (ECF_NOTHROW | ECF_NORETURN))
+             != (ECF_NOTHROW | ECF_NORETURN))
+           local->calls_write_all = true;
+       }
+    }
+}
+
+/* TP is the part of the tree currently under the microscope.
+   WALK_SUBTREES is part of the walk_tree api but is unused here.
+   DATA is cgraph_node of the function being walked.  */
+
+static tree
+scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
+                          struct cgraph_node *fn)
+{
+  gimple stmt = gsi_stmt (*gsip);
+  ipa_reference_local_vars_info_t local = NULL;
+
+  if (is_gimple_debug (stmt))
+    return NULL;
+
+  if (fn)
+    local = get_reference_vars_info (fn)->local;
+
+  /* Look for direct loads and stores.  */
+  walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store,
+                                mark_address);
+
+  if (is_gimple_call (stmt))
+    check_call (local, stmt);
+  else if (gimple_code (stmt) == GIMPLE_ASM)
+    check_asm_memory_clobber (local, stmt);
+
+  return NULL;
+}
+
+/* Call-back to scan variable initializers for static references.
+   Called using walk_tree.  */
+
+static tree
+scan_initializer_for_static_refs (tree *tp, int *walk_subtrees,
+                                 void *data ATTRIBUTE_UNUSED)
+{
+  tree t = *tp;
+
+  if (TREE_CODE (t) == ADDR_EXPR)
+    {
+      mark_address_taken (get_base_var (t));
+      *walk_subtrees = 0;
+    }
+  /* Save some cycles by not walking types and declaration as we
+     won't find anything useful there anyway.  */
+  else if (IS_TYPE_OR_DECL_P (*tp))
+    *walk_subtrees = 0;
+
+  return NULL;
+}
+
+/* Lookup the tree node for the static variable that has UID.  */
+static tree
+get_static_decl (int index)
+{
+  splay_tree_node stn =
+    splay_tree_lookup (reference_vars_to_consider, index);
+  if (stn)
+    return (tree)stn->value;
+  return NULL;
+}
+
 /* Lookup the tree node for the static variable that has UID and
    convert the name to a string for debugging.  */
 
index f688d10..4ce9ba2 100644 (file)
@@ -1859,6 +1859,80 @@ optimize_stdarg_builtin (gimple call)
     }
 }
 
+/* Convert EXPR into a GIMPLE value suitable for substitution on the
+   RHS of an assignment.  Insert the necessary statements before
+   iterator *SI_P.  The statement at *SI_P, which must be a GIMPLE_CALL
+   is replaced.  If the call is expected to produces a result, then it
+   is replaced by an assignment of the new RHS to the result variable.
+   If the result is to be ignored, then the call is replaced by a
+   GIMPLE_NOP.  */
+
+static void
+gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
+{
+  tree lhs;
+  tree tmp = NULL_TREE;  /* Silence warning.  */
+  gimple stmt, new_stmt;
+  gimple_stmt_iterator i;
+  gimple_seq stmts = gimple_seq_alloc();
+  struct gimplify_ctx gctx;
+  gimple last = NULL;
+
+  stmt = gsi_stmt (*si_p);
+
+  gcc_assert (is_gimple_call (stmt));
+
+  lhs = gimple_call_lhs (stmt);
+
+  push_gimplify_context (&gctx);
+
+  if (lhs == NULL_TREE)
+    gimplify_and_add (expr, &stmts);
+  else
+    tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+
+  pop_gimplify_context (NULL);
+
+  if (gimple_has_location (stmt))
+    annotate_all_with_location (stmts, gimple_location (stmt));
+
+  /* The replacement can expose previously unreferenced variables.  */
+  for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
+    {
+      if (last)
+       {
+         gsi_insert_before (si_p, last, GSI_NEW_STMT);
+         gsi_next (si_p);
+       }
+      new_stmt = gsi_stmt (i);
+      find_new_referenced_vars (new_stmt);
+      mark_symbols_for_renaming (new_stmt);
+      last = new_stmt;
+    }
+
+  if (lhs == NULL_TREE)
+    {
+      unlink_stmt_vdef (stmt);
+      release_defs (stmt);
+      new_stmt = last;
+    }
+  else
+    {
+      if (last)
+       {
+         gsi_insert_before (si_p, last, GSI_NEW_STMT);
+         gsi_next (si_p);
+       }
+      new_stmt = gimple_build_assign (lhs, tmp);
+      gimple_set_vuse (new_stmt, gimple_vuse (stmt));
+      gimple_set_vdef (new_stmt, gimple_vdef (stmt));
+      move_ssa_defining_stmt_for_defs (new_stmt, stmt);
+    }
+
+  gimple_set_location (new_stmt, gimple_location (stmt));
+  gsi_replace (si_p, new_stmt, false);
+}
+
 /* A simple pass that attempts to fold all builtin functions.  This pass
    is run after we've propagated as many constants as we can.  */