]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple.h (walk_stmt_load_store_addr_ops): Declare.
authorRichard Guenther <rguenther@suse.de>
Thu, 16 Apr 2009 13:22:03 +0000 (13:22 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 16 Apr 2009 13:22:03 +0000 (13:22 +0000)
2009-04-16  Richard Guenther  <rguenther@suse.de>

* gimple.h (walk_stmt_load_store_addr_ops): Declare.
(walk_stmt_load_store_ops): Likewise.
* gimple.c (get_base_loadstore): New function.
(walk_stmt_load_store_addr_ops): Likewise.
(walk_stmt_load_store_ops): Likewise.
* ipa-pure-const.c (check_op): Simplify.
(check_load, check_store): New functions.
(check_stmt): Use walk_stmt_load_store_ops.
* ipa-reference.c (mark_load): Adjust signature.
(mark_store): Likewise.
(scan_stmt_for_static_refs): Use walk_stmt_load_store_addr_ops.

From-SVN: r146190

gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h
gcc/ipa-pure-const.c
gcc/ipa-reference.c

index 8179454cbe73ba7601a8b7b422e767f19c2873c4..7bcff75da26a8ec1ec397ee9a6c2010750721832 100644 (file)
@@ -1,3 +1,17 @@
+2009-04-16  Richard Guenther  <rguenther@suse.de>
+
+       * gimple.h (walk_stmt_load_store_addr_ops): Declare.
+       (walk_stmt_load_store_ops): Likewise.
+       * gimple.c (get_base_loadstore): New function.
+       (walk_stmt_load_store_addr_ops): Likewise.
+       (walk_stmt_load_store_ops): Likewise.
+       * ipa-pure-const.c (check_op): Simplify.
+       (check_load, check_store): New functions.
+       (check_stmt): Use walk_stmt_load_store_ops.
+       * ipa-reference.c (mark_load): Adjust signature.
+       (mark_store): Likewise.
+       (scan_stmt_for_static_refs): Use walk_stmt_load_store_addr_ops.
+
 2009-04-16  Rafael Avila de Espindola  <espindola@google.com>
 
        * gcc-plugin.h (plugin_event): Add PLUGIN_INFO.
index 4d05c983e9d76a7e9ac21840bd0c6347ab213922..29692782aed894ca26d708a11f10d0b3db2705b8 100644 (file)
@@ -3194,4 +3194,202 @@ count_uses_and_derefs (tree ptr, gimple stmt, unsigned *num_uses_p,
   gcc_assert (*num_uses_p >= *num_loads_p + *num_stores_p);
 }
 
+/* From a tree operand OP return the base of a load or store operation
+   or NULL_TREE if OP is not a load or a store.  */
+
+static tree
+get_base_loadstore (tree op)
+{
+  while (handled_component_p (op))
+    op = TREE_OPERAND (op, 0);
+  if (DECL_P (op)
+      || INDIRECT_REF_P (op)
+      || TREE_CODE (op) == TARGET_MEM_REF)
+    return op;
+  return NULL_TREE;
+}
+
+/* For the statement STMT call the callbacks VISIT_LOAD, VISIT_STORE and
+   VISIT_ADDR if non-NULL on loads, store and address-taken operands
+   passing the STMT, the base of the operand and DATA to it.  The base
+   will be either a decl, an indirect reference (including TARGET_MEM_REF)
+   or the argument of an address expression.
+   Returns the results of these callbacks or'ed.  */
+
+bool
+walk_stmt_load_store_addr_ops (gimple stmt, void *data,
+                              bool (*visit_load)(gimple, tree, void *),
+                              bool (*visit_store)(gimple, tree, void *),
+                              bool (*visit_addr)(gimple, tree, void *))
+{
+  bool ret = false;
+  unsigned i;
+  if (gimple_assign_single_p (stmt))
+    {
+      tree lhs, rhs;
+      if (visit_store)
+       {
+         lhs = get_base_loadstore (gimple_assign_lhs (stmt));
+         if (lhs)
+           ret |= visit_store (stmt, lhs, data);
+       }
+      rhs = gimple_assign_rhs1 (stmt);
+      if (visit_addr)
+       {
+         if (TREE_CODE (rhs) == ADDR_EXPR)
+           ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+         else if (TREE_CODE (rhs) == TARGET_MEM_REF
+                  && TREE_CODE (TMR_BASE (rhs)) == ADDR_EXPR)
+           ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (rhs), 0), data);
+         else if (TREE_CODE (rhs) == OBJ_TYPE_REF
+                  && TREE_CODE (OBJ_TYPE_REF_OBJECT (rhs)) == ADDR_EXPR)
+           ret |= visit_addr (stmt, TREE_OPERAND (OBJ_TYPE_REF_OBJECT (rhs),
+                                                  0), data);
+       }
+      if (visit_load)
+       {
+         rhs = get_base_loadstore (rhs);
+         if (rhs)
+           ret |= visit_load (stmt, rhs, data);
+       }
+    }
+  else if (visit_addr
+          && (is_gimple_assign (stmt)
+              || gimple_code (stmt) == GIMPLE_COND
+              || gimple_code (stmt) == GIMPLE_CHANGE_DYNAMIC_TYPE))
+    {
+      for (i = 0; i < gimple_num_ops (stmt); ++i)
+       if (gimple_op (stmt, i)
+           && TREE_CODE (gimple_op (stmt, i)) == ADDR_EXPR)
+         ret |= visit_addr (stmt, TREE_OPERAND (gimple_op (stmt, i), 0), data);
+    }
+  else if (is_gimple_call (stmt))
+    {
+      if (visit_store)
+       {
+         tree lhs = gimple_call_lhs (stmt);
+         if (lhs)
+           {
+             lhs = get_base_loadstore (lhs);
+             if (lhs)
+               ret |= visit_store (stmt, lhs, data);
+           }
+       }
+      if (visit_load || visit_addr)
+       for (i = 0; i < gimple_call_num_args (stmt); ++i)
+         {
+           tree rhs = gimple_call_arg (stmt, i);
+           if (visit_addr
+               && TREE_CODE (rhs) == ADDR_EXPR)
+             ret |= visit_addr (stmt, TREE_OPERAND (rhs, 0), data);
+           else if (visit_load)
+             {
+               rhs = get_base_loadstore (rhs);
+               if (rhs)
+                 ret |= visit_load (stmt, rhs, data);
+             }
+         }
+      if (visit_addr
+         && gimple_call_chain (stmt)
+         && TREE_CODE (gimple_call_chain (stmt)) == ADDR_EXPR)
+       ret |= visit_addr (stmt, TREE_OPERAND (gimple_call_chain (stmt), 0),
+                          data);
+    }
+  else if (gimple_code (stmt) == GIMPLE_ASM)
+    {
+      unsigned noutputs;
+      const char *constraint;
+      const char **oconstraints;
+      bool allows_mem, allows_reg, is_inout;
+      noutputs = gimple_asm_noutputs (stmt);
+      oconstraints = XALLOCAVEC (const char *, noutputs);
+      if (visit_store || visit_addr)
+       for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
+         {
+           tree link = gimple_asm_output_op (stmt, i);
+           tree op = get_base_loadstore (TREE_VALUE (link));
+           if (op && visit_store)
+             ret |= visit_store (stmt, op, data);
+           if (visit_addr)
+             {
+               constraint = TREE_STRING_POINTER
+                   (TREE_VALUE (TREE_PURPOSE (link)));
+               oconstraints[i] = constraint;
+               parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+                                        &allows_reg, &is_inout);
+               if (op && !allows_reg && allows_mem)
+                 ret |= visit_addr (stmt, op, data);
+             }
+         }
+      if (visit_load || visit_addr)
+       for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
+         {
+           tree link = gimple_asm_input_op (stmt, i);
+           tree op = TREE_VALUE (link);
+           if (visit_addr
+               && TREE_CODE (op) == ADDR_EXPR)
+             ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+           else if (visit_load || visit_addr)
+             {
+               op = get_base_loadstore (op);
+               if (op)
+                 {
+                   if (visit_load)
+                     ret |= visit_load (stmt, op, data);
+                   if (visit_addr)
+                     {
+                       constraint = TREE_STRING_POINTER
+                           (TREE_VALUE (TREE_PURPOSE (link)));
+                       parse_input_constraint (&constraint, 0, 0, noutputs,
+                                               0, oconstraints,
+                                               &allows_mem, &allows_reg);
+                       if (!allows_reg && allows_mem)
+                         ret |= visit_addr (stmt, op, data);
+                     }
+                 }
+             }
+         }
+    }
+  else if (gimple_code (stmt) == GIMPLE_RETURN)
+    {
+      tree op = gimple_return_retval (stmt);
+      if (op)
+       {
+         if (visit_addr
+             && TREE_CODE (op) == ADDR_EXPR)
+           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+         else if (visit_load)
+           {
+             op = get_base_loadstore (op);
+             if (op)
+               ret |= visit_load (stmt, op, data);
+           }
+       }
+    }
+  else if (visit_addr
+          && gimple_code (stmt) == GIMPLE_PHI)
+    {
+      for (i = 0; i < gimple_phi_num_args (stmt); ++i)
+       {
+         tree op = PHI_ARG_DEF (stmt, i);
+         if (TREE_CODE (op) == ADDR_EXPR)
+           ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+       }
+    }
+
+  return ret;
+}
+
+/* Like walk_stmt_load_store_addr_ops but with NULL visit_addr.  IPA-CP
+   should make a faster clone for this case.  */
+
+bool
+walk_stmt_load_store_ops (gimple stmt, void *data,
+                         bool (*visit_load)(gimple, tree, void *),
+                         bool (*visit_store)(gimple, tree, void *))
+{
+  return walk_stmt_load_store_addr_ops (stmt, data,
+                                       visit_load, visit_store, NULL);
+}
+
 #include "gt-gimple.h"
index dde7f942e16451bf8a6770a84c824891020df2a7..bf09039a5e97905f9ea7b2a4701ef698af5bab88 100644 (file)
@@ -909,6 +909,13 @@ extern tree get_call_expr_in (tree t);
 extern void recalculate_side_effects (tree);
 extern void count_uses_and_derefs (tree, gimple, unsigned *, unsigned *,
                                   unsigned *);
+extern bool walk_stmt_load_store_addr_ops (gimple, void *,
+                                          bool (*)(gimple, tree, void *),
+                                          bool (*)(gimple, tree, void *),
+                                          bool (*)(gimple, tree, void *));
+extern bool walk_stmt_load_store_ops (gimple, void *,
+                                     bool (*)(gimple, tree, void *),
+                                     bool (*)(gimple, tree, void *));
 
 /* In gimplify.c  */
 extern tree create_tmp_var_raw (tree, const char *);
index a8c4b1b310b9d8439fdf67f688620532e27984f5..ca4da1c6a6cf097ed8477f720e1785febb738c24 100644 (file)
@@ -209,36 +209,28 @@ check_decl (funct_state local,
    variable T is legal in a function that is either pure or const.  */
 
 static inline void 
-check_op (funct_state local, 
-           tree t, bool checking_write)
+check_op (funct_state local, tree t, bool checking_write)
 {
-  while (t && handled_component_p (t))
-    t = TREE_OPERAND (t, 0);
-  if (!t)
-    return;
-  if (INDIRECT_REF_P (t) || TREE_CODE (t) == TARGET_MEM_REF)
+  if (TREE_THIS_VOLATILE (t))
     {
-      if (TREE_THIS_VOLATILE (t)) 
-       { 
-         local->pure_const_state = IPA_NEITHER;
-         if (dump_file)
-           fprintf (dump_file, "    Volatile indirect ref is not const/pure\n");
-         return;
-       }
-      else if (checking_write)
-       { 
-         local->pure_const_state = IPA_NEITHER;
-         if (dump_file)
-           fprintf (dump_file, "    Indirect ref write is not const/pure\n");
-         return;
-       }
-       else
-        {
-         if (dump_file)
-           fprintf (dump_file, "    Indirect ref read is not const\n");
-          if (local->pure_const_state == IPA_CONST)
-           local->pure_const_state = IPA_PURE;
-       }
+      local->pure_const_state = IPA_NEITHER;
+      if (dump_file)
+       fprintf (dump_file, "    Volatile indirect ref is not const/pure\n");
+      return;
+    }
+  else if (checking_write)
+    {
+      local->pure_const_state = IPA_NEITHER;
+      if (dump_file)
+       fprintf (dump_file, "    Indirect ref write is not const/pure\n");
+      return;
+    }
+  else
+    {
+      if (dump_file)
+       fprintf (dump_file, "    Indirect ref read is not const\n");
+      if (local->pure_const_state == IPA_CONST)
+       local->pure_const_state = IPA_PURE;
     }
 }
 
@@ -375,6 +367,30 @@ check_call (funct_state local, gimple call, bool ipa)
   /* Direct functions calls are handled by IPA propagation.  */
 }
 
+/* Wrapper around check_decl for loads.  */
+
+static bool
+check_load (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+{
+  if (DECL_P (op))
+    check_decl ((funct_state)data, op, false);
+  else
+    check_op ((funct_state)data, op, false);
+  return false;
+}
+
+/* Wrapper around check_decl for stores.  */
+
+static bool
+check_store (gimple stmt ATTRIBUTE_UNUSED, tree op, void *data)
+{
+  if (DECL_P (op))
+    check_decl ((funct_state)data, op, true);
+  else
+    check_op ((funct_state)data, op, true);
+  return false;
+}
+
 /* Look into pointer pointed to by GSIP and figure out what interesting side
    effects it has.  */
 static void
@@ -389,45 +405,8 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
       print_gimple_stmt (dump_file, stmt, 0, 0);
     }
 
-  /* Look for direct loads and stores.  */
-  if (gimple_has_lhs (stmt))
-    {
-      tree lhs = get_base_address (gimple_get_lhs (stmt));
-      if (lhs && DECL_P (lhs))
-       check_decl (local, lhs, true);
-    }
-  if (gimple_assign_single_p (stmt))
-    {
-      tree rhs = get_base_address (gimple_assign_rhs1 (stmt));
-      if (rhs && DECL_P (rhs))
-       check_decl (local, rhs, false);
-    }
-  else if (is_gimple_call (stmt))
-    {
-      for (i = 0; i < gimple_call_num_args (stmt); ++i)
-       {
-         tree rhs = get_base_address (gimple_call_arg (stmt, i));
-         if (rhs && DECL_P (rhs))
-           check_decl (local, rhs, false);
-       }
-    }
-  else if (gimple_code (stmt) == GIMPLE_ASM)
-    {
-      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
-       {
-         tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
-         op = get_base_address (op);
-         if (op && DECL_P (op))
-           check_decl (local, op, false);
-       }
-      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
-       {
-         tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
-         op = get_base_address (op);
-         if (op && DECL_P (op))
-           check_decl (local, op, true);
-       }
-    }
+  /* Look for loads and stores.  */
+  walk_stmt_load_store_ops (stmt, local, check_load, check_store);
 
   if (gimple_code (stmt) != GIMPLE_CALL
       && stmt_could_throw_p (stmt))
@@ -447,13 +426,7 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
     }
   switch (gimple_code (stmt))
     {
-    case GIMPLE_ASSIGN:
-      check_op (local, gimple_assign_lhs (stmt), true);
-      i = 1;
-      break;
     case GIMPLE_CALL:
-      check_op (local, gimple_call_lhs (stmt), true);
-      i = 1;
       check_call (local, stmt, ipa);
       break;
     case GIMPLE_LABEL:
@@ -466,10 +439,6 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
        }
       break;
     case GIMPLE_ASM:
-      for (i = 0; i < gimple_asm_noutputs (stmt); i++)
-         check_op (local, TREE_VALUE (gimple_asm_output_op (stmt, i)), true);
-      for (i = 0; i < gimple_asm_ninputs (stmt); i++)
-         check_op (local, TREE_VALUE (gimple_asm_input_op (stmt, i)), false);
       for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
        {
          tree op = gimple_asm_clobber_op (stmt, i);
@@ -493,9 +462,6 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa)
     default:
       break;
     }
-
-  for (; i < gimple_num_ops (stmt); i++)
-    check_op (local, gimple_op (stmt, i), false);
 }
 
 
index 4bc49cf0a058500d7037551f9ac6b94e00ccc7ad..d2c20c08d16f32e34e42a26a418fc71f964884c9 100644 (file)
@@ -336,21 +336,22 @@ mark_address_taken (tree x)
 
 /* Mark load of T.  */
 
-static void
-mark_load (ipa_reference_local_vars_info_t local, 
-          tree 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;
   if (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 void
-mark_store (ipa_reference_local_vars_info_t local, 
-          tree 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;
   if (TREE_CODE (t) == VAR_DECL
       && has_proper_scope_for_analysis (t))
     {
@@ -361,6 +362,7 @@ mark_store (ipa_reference_local_vars_info_t local,
       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.  */
@@ -434,46 +436,12 @@ scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
     local = get_reference_vars_info (fn)->local;
 
   /* Look for direct loads and stores.  */
-  if (gimple_has_lhs (stmt))
-    {
-      tree lhs = get_base_address (gimple_get_lhs (stmt));
-      if (lhs && DECL_P (lhs))
-        mark_store (local, lhs);
-    }
-  if (gimple_assign_single_p (stmt))
-    {
-      tree rhs = get_base_address (gimple_assign_rhs1 (stmt));
-      if (rhs && DECL_P (rhs))
-       mark_load (local, rhs);
-    }
-  else if (is_gimple_call (stmt))
-    {
-      for (i = 0; i < gimple_call_num_args (stmt); ++i)
-       {
-         tree rhs = get_base_address (gimple_call_arg (stmt, i));
-         if (rhs && DECL_P (rhs))
-           mark_load (local, rhs);
-       }
-      check_call (local, stmt);
-    }
+  walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store, NULL);
+
+  if (is_gimple_call (stmt))
+    check_call (local, stmt);
   else if (gimple_code (stmt) == GIMPLE_ASM)
-    {
-      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
-       {
-         tree op = TREE_VALUE (gimple_asm_input_op (stmt, i));
-         op = get_base_address (op);
-         if (op && DECL_P (op))
-           mark_load (local, op);
-       }
-      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
-       {
-         tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
-         op = get_base_address (op);
-         if (op && DECL_P (op))
-           mark_store (local, op);
-       }
-      check_asm_memory_clobber (local, stmt);
-    }
+    check_asm_memory_clobber (local, stmt);
 
   if (gimple_addresses_taken (stmt))
     EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt), 0, i, bi)