tree.c (decl_address_ip_invariant_p): New function.
authorJan Hubicka <jh@suse.cz>
Sat, 23 Aug 2008 20:28:07 +0000 (22:28 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 23 Aug 2008 20:28:07 +0000 (20:28 +0000)
* tree.c (decl_address_ip_invariant_p): New function.
* tree.h (decl_address_ip_invariant_p): Declare.
* gimple.c (strip_invariant_refs): Break out from ...
(is_gimple_invariant_address): ... here
(is_gimple_ip_invariant_address): New function.
(is_gimple_ip_invariant): New function.
* gimple.h (is_gimple_ip_invariant_address, is_gimple_ip_invariant):
Declare.

* ipa-cp.c (ipcp_lat_is_const): Remove handling of IPA_CONST_VALUE_REF.
(ipcp_lat_is_insertable): All constants are insertable.
(ipcp_lattice_from_jfunc, ipcp_print_all_lattices): Remove handling of
IPA_CONST_VALUE_REF.
(ipcp_initialize_node_lattices): Propagate all types of operands.
(build_const_val): Do not handle IPA_CONST_VALUE_REF.
(ipcp_create_replace_map): Reformat.
(ipcp_need_redirect_p): Simplify.
(ipcp_insert_stage): Check that argument is used before clonning.
* ipa-prop.c (ipa_print_node_jump_functions): Do not handle IPA_CONST_REF.
(compute_scalar_jump_functions): Simplify using is_gimple_ip_invariat.
(determine_cst_member_ptr): Keep wrapping ADDR_EXPR of members.
(update_call_notes_after_inlining): Expect ADDR_EXPR in operand.
* ipa-prop.h (jump_func_type): Remove IPA_CONST_REF.
(jump_func_type): Remove IPA_CONST_VALUE_REF.
* tree-inline.c (tree_function_versioning): Add variables referenced by
replacing trees.

From-SVN: r139523

gcc/ChangeLog
gcc/gimple.c
gcc/gimple.h
gcc/ipa-cp.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/tree-inline.c
gcc/tree.c
gcc/tree.h

index 0a08808d220340a9517bcf154e47ffb2ec180330..33605b99b5ba47dc40d86b56a639d154fd9c7840 100644 (file)
@@ -1,3 +1,32 @@
+2008-08-23  Jan Hubicka  <jh@suse.cz>
+
+       * tree.c (decl_address_ip_invariant_p): New function.
+       * tree.h (decl_address_ip_invariant_p): Declare.
+       * gimple.c (strip_invariant_refs): Break out from ...
+       (is_gimple_invariant_address): ... here
+       (is_gimple_ip_invariant_address): New function.
+       (is_gimple_ip_invariant): New function.
+       * gimple.h (is_gimple_ip_invariant_address, is_gimple_ip_invariant):
+       Declare.
+
+       * ipa-cp.c (ipcp_lat_is_const): Remove handling of IPA_CONST_VALUE_REF.
+       (ipcp_lat_is_insertable): All constants are insertable.
+       (ipcp_lattice_from_jfunc, ipcp_print_all_lattices): Remove handling of
+       IPA_CONST_VALUE_REF.
+       (ipcp_initialize_node_lattices): Propagate all types of operands.
+       (build_const_val): Do not handle IPA_CONST_VALUE_REF.
+       (ipcp_create_replace_map): Reformat.
+       (ipcp_need_redirect_p): Simplify.
+       (ipcp_insert_stage): Check that argument is used before clonning.
+       * ipa-prop.c (ipa_print_node_jump_functions): Do not handle IPA_CONST_REF.
+       (compute_scalar_jump_functions): Simplify using is_gimple_ip_invariat.
+       (determine_cst_member_ptr): Keep wrapping ADDR_EXPR of members.
+       (update_call_notes_after_inlining): Expect ADDR_EXPR in operand.
+       * ipa-prop.h (jump_func_type): Remove IPA_CONST_REF.
+       (jump_func_type): Remove IPA_CONST_VALUE_REF.
+       * tree-inline.c (tree_function_versioning): Add variables referenced by
+       replacing trees.
+
 2008-08-23  Jan Hubicka  <jh@suse.cz>
 
        PR target/37094
index 9e7d92155b033f700fbf2f2d92d7de3cc87d1fcb..c651f0db9c313c6bbfa0b8474135d3e296847f6c 100644 (file)
@@ -2730,17 +2730,12 @@ is_gimple_address (const_tree t)
     }
 }
 
-/* Return true if T is a gimple invariant address.  */
+/* Strip out all handled components that produce invariant
+   offsets.  */
 
-bool
-is_gimple_invariant_address (const_tree t)
+static const_tree
+strip_invariant_refs (const_tree op)
 {
-  tree op;
-
-  if (TREE_CODE (t) != ADDR_EXPR)
-    return false;
-
-  op = TREE_OPERAND (t, 0);
   while (handled_component_p (op))
     {
       switch (TREE_CODE (op))
@@ -2750,12 +2745,12 @@ is_gimple_invariant_address (const_tree t)
          if (!is_gimple_constant (TREE_OPERAND (op, 1))
              || TREE_OPERAND (op, 2) != NULL_TREE
              || TREE_OPERAND (op, 3) != NULL_TREE)
-           return false;
+           return NULL;
          break;
 
        case COMPONENT_REF:
          if (TREE_OPERAND (op, 2) != NULL_TREE)
-           return false;
+           return NULL;
          break;
 
        default:;
@@ -2763,7 +2758,38 @@ is_gimple_invariant_address (const_tree t)
       op = TREE_OPERAND (op, 0);
     }
 
-  return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op);
+  return op;
+}
+
+/* Return true if T is a gimple invariant address.  */
+
+bool
+is_gimple_invariant_address (const_tree t)
+{
+  const_tree op;
+
+  if (TREE_CODE (t) != ADDR_EXPR)
+    return false;
+
+  op = strip_invariant_refs (TREE_OPERAND (t, 0));
+
+  return op && (CONSTANT_CLASS_P (op) || decl_address_invariant_p (op));
+}
+
+/* Return true if T is a gimple invariant address at IPA level
+   (so addresses of variables on stack are not allowed).  */
+
+bool
+is_gimple_ip_invariant_address (const_tree t)
+{
+  const_tree op;
+
+  if (TREE_CODE (t) != ADDR_EXPR)
+    return false;
+
+  op = strip_invariant_refs (TREE_OPERAND (t, 0));
+
+  return op && (CONSTANT_CLASS_P (op) || decl_address_ip_invariant_p (op));
 }
 
 /* Return true if T is a GIMPLE minimal invariant.  It's a restricted
@@ -2778,6 +2804,18 @@ is_gimple_min_invariant (const_tree t)
   return is_gimple_constant (t);
 }
 
+/* Return true if T is a GIMPLE interprocedural invariant.  It's a restricted
+   form of gimple minimal invariant.  */
+
+bool
+is_gimple_ip_invariant (const_tree t)
+{
+  if (TREE_CODE (t) == ADDR_EXPR)
+    return is_gimple_ip_invariant_address (t);
+
+  return is_gimple_constant (t);
+}
+
 /* Return true if T looks like a valid GIMPLE statement.  */
 
 bool
index 7072edfb1b51fa49bcfa37f4c0b0608ad55d64bb..ebb8eebc1f2d9bcad058152647aeba4b77efff1f 100644 (file)
@@ -872,10 +872,15 @@ extern bool is_gimple_lvalue (tree);
 bool is_gimple_address (const_tree);
 /* Returns true iff T is a GIMPLE invariant address.  */
 bool is_gimple_invariant_address (const_tree);
+/* Returns true iff T is a GIMPLE invariant address at interprocedural
+   level.  */
+bool is_gimple_ip_invariant_address (const_tree);
 /* Returns true iff T is a valid GIMPLE constant.  */
 bool is_gimple_constant (const_tree);
 /* Returns true iff T is a GIMPLE restricted function invariant.  */
 extern bool is_gimple_min_invariant (const_tree);
+/* Returns true iff T is a GIMPLE restricted interprecodural invariant.  */
+extern bool is_gimple_ip_invariant (const_tree);
 /* Returns true iff T is a GIMPLE rvalue.  */
 extern bool is_gimple_val (tree);
 /* Returns true iff T is a GIMPLE asm statement input.  */
index d534d198203f7f40e2d6f7b2e43df85f90355991..868a57caec34768419e621a4a6575eab3d3d1bf1 100644 (file)
@@ -207,7 +207,7 @@ ipcp_set_node_scale (struct cgraph_node *node, gcov_type count)
 static inline bool
 ipcp_lat_is_const (struct ipcp_lattice *lat)
 {
-  if (lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
+  if (lat->type == IPA_CONST_VALUE)
     return true;
   else
     return false;
@@ -218,11 +218,7 @@ ipcp_lat_is_const (struct ipcp_lattice *lat)
 static inline bool
 ipcp_lat_is_insertable (struct ipcp_lattice *lat)
 {
-  if ((lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
-      && !POINTER_TYPE_P (TREE_TYPE (lat->constant)))
-    return true;
-  else
-    return false;
+  return lat->type == IPA_CONST_VALUE;
 }
 
 /* Return true if LAT1 and LAT2 are equal.  */
@@ -294,11 +290,6 @@ ipcp_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
       lat->type = IPA_CONST_VALUE;
       lat->constant = jfunc->value.constant;
     }
-  else if (jfunc->type == IPA_CONST_REF)
-    {
-      lat->type = IPA_CONST_VALUE_REF;
-      lat->constant = jfunc->value.constant;
-    }
   else if (jfunc->type == IPA_PASS_THROUGH)
     {
       struct ipcp_lattice *caller_lat;
@@ -349,7 +340,7 @@ ipcp_print_all_lattices (FILE * f)
          struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
 
          fprintf (f, " param [%d]: ", i);
-         if (lat->type == IPA_CONST_VALUE || lat->type == IPA_CONST_VALUE_REF)
+         if (lat->type == IPA_CONST_VALUE)
            {
              fprintf (f, "type is CONST ");
              print_generic_expr (f, lat->constant, 0);
@@ -375,17 +366,7 @@ ipcp_initialize_node_lattices (struct cgraph_node *node)
   info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice,
                                  ipa_get_param_count (info));
   for (i = 0; i < ipa_get_param_count (info) ; i++)
-    {
-      tree parm_tree = ipa_get_ith_param (info, i);
-      struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-
-      if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree))
-         || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree))
-         || POINTER_TYPE_P (TREE_TYPE (parm_tree)))
-       lat->type = IPA_TOP;
-      else
-       lat->type = IPA_BOTTOM;
-    }
+    ipcp_get_ith_lattice (info, i)->type = IPA_TOP;
 }
 
 /* Create a new assignment statement and make it the first statement in the
@@ -412,14 +393,6 @@ build_const_val (struct ipcp_lattice *lat, tree tree_type)
   gcc_assert (ipcp_lat_is_const (lat));
   val = lat->constant;
 
-  /* compute_jump_functions inserts FUNCTION_DECL as value of parameter
-     when address of function is taken.  It would make more sense to pass
-     whole ADDR_EXPR, but for now compensate here.  */
-  if ((lat->type == IPA_CONST_VALUE
-        && TREE_CODE (val) == FUNCTION_DECL)
-      || lat->type == IPA_CONST_VALUE_REF)
-    return build_fold_addr_expr_with_type (val, tree_type);
-
   if (!useless_type_conversion_p (tree_type, TREE_TYPE (val)))
     {
       if (fold_convertible_p (tree_type, val))
@@ -789,7 +762,8 @@ ipcp_create_replace_map (struct function *func, tree parm_tree,
   tree const_val;
 
   replace_map = XCNEW (struct ipa_replace_map);
-  if (is_gimple_reg (parm_tree) && gimple_default_def (func, parm_tree)
+  if (is_gimple_reg (parm_tree)
+      && gimple_default_def (func, parm_tree)
       && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_default_def (func,
                                                                 parm_tree)))
     {
@@ -829,8 +803,7 @@ ipcp_need_redirect_p (struct cgraph_edge *cs)
       if (ipcp_lat_is_const (lat))
        {
          jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
-         if (jump_func->type != IPA_CONST && jump_func->type != IPA_CONST_REF
-             && jump_func->type != IPA_CONST_MEMBER_PTR)
+         if (jump_func->type != IPA_CONST)
            return true;
        }
     }
@@ -949,7 +922,11 @@ ipcp_insert_stage (void)
       for (i = 0; i < count; i++)
        {
          struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-         if (ipcp_lat_is_insertable (lat))
+         tree parm_tree = ipa_get_ith_param (info, i);
+         if (ipcp_lat_is_insertable (lat)
+             /* Do not count obviously unused arguments.  */
+             && (!is_gimple_reg (parm_tree)
+                 || gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm_tree)))
            const_param++;
        }
       if (const_param == 0)
@@ -958,8 +935,7 @@ ipcp_insert_stage (void)
       for (i = 0; i < count; i++)
        {
          struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i);
-         if (lat->type == IPA_CONST_VALUE
-             && !POINTER_TYPE_P (TREE_TYPE (lat->constant)))
+         if (lat->type == IPA_CONST_VALUE)
            {
              parm_tree = ipa_get_ith_param (info, i);
              replace_param =
@@ -999,8 +975,7 @@ ipcp_insert_stage (void)
              if (ipcp_lat_is_insertable (lat))
                {
                  parm_tree = ipa_get_ith_param (info, i);
-                 if (lat->type != IPA_CONST_VALUE_REF
-                     && !is_gimple_reg (parm_tree))
+                 if (!is_gimple_reg (parm_tree))
                    ipcp_propagate_one_const (node1, i, lat);
                }
            }
index 5a93a4a7311d6595960cd40ee5ed773f45d621f2..506a9400e151e26af7260855756c7b496a962c4b 100644 (file)
@@ -273,7 +273,7 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
          fprintf (f, "  param %d: ", i);
          if (type == IPA_UNKNOWN)
            fprintf (f, "UNKNOWN\n");
-         else if (type == IPA_CONST || type == IPA_CONST_REF)
+         else if (type == IPA_CONST)
            {
              tree val = jump_func->value.constant;
              fprintf (f, "CONST: ");
@@ -327,33 +327,11 @@ compute_scalar_jump_functions (struct ipa_node_params *info,
     {
       arg = gimple_call_arg (call, num);
 
-      if (TREE_CODE (arg) == INTEGER_CST
-         || TREE_CODE (arg) == REAL_CST
-         || TREE_CODE (arg) == FIXED_CST)
+      if (is_gimple_ip_invariant (arg))
        {
          functions[num].type = IPA_CONST;
          functions[num].value.constant = arg;
        }
-      else if (TREE_CODE (arg) == ADDR_EXPR)
-       {
-         if (TREE_CODE (TREE_OPERAND (arg, 0)) == FUNCTION_DECL)
-           {
-             functions[num].type = IPA_CONST;
-             functions[num].value.constant = TREE_OPERAND (arg, 0);
-           }
-         else if (TREE_CODE (TREE_OPERAND (arg, 0)) == CONST_DECL)
-           {
-             tree cst_decl = TREE_OPERAND (arg, 0);
-
-             if (TREE_CODE (DECL_INITIAL (cst_decl)) == INTEGER_CST
-                 || TREE_CODE (DECL_INITIAL (cst_decl)) == REAL_CST
-                 || TREE_CODE (DECL_INITIAL (cst_decl)) == FIXED_CST)
-               {
-                 functions[num].type = IPA_CONST_REF;
-                 functions[num].value.constant = cst_decl;
-               }
-           }
-       }
       else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg))
        {
          int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg));
@@ -496,7 +474,7 @@ determine_cst_member_ptr (gimple call, tree arg, tree method_field,
              method = TREE_OPERAND (rhs, 0);
              if (delta)
                {
-                 fill_member_ptr_cst_jump_function (jfunc, method, delta);
+                 fill_member_ptr_cst_jump_function (jfunc, rhs, delta);
                  return;
                }
            }
@@ -511,7 +489,7 @@ determine_cst_member_ptr (gimple call, tree arg, tree method_field,
              delta = rhs;
              if (method)
                {
-                 fill_member_ptr_cst_jump_function (jfunc, method, delta);
+                 fill_member_ptr_cst_jump_function (jfunc, rhs, delta);
                  return;
                }
            }
@@ -952,6 +930,10 @@ update_call_notes_after_inlining (struct cgraph_edge *cs,
          else
            decl = jfunc->value.constant;
 
+         if (TREE_CODE (decl) != ADDR_EXPR)
+           continue;
+         decl = TREE_OPERAND (decl, 0);
+
          if (TREE_CODE (decl) != FUNCTION_DECL)
            continue;
          callee = cgraph_node (decl);
index 908a97e7797899753ee064e3acb24b6ef63716da..967825e21f8de391dad738429d127d3fa755b4fa 100644 (file)
@@ -32,14 +32,12 @@ along with GCC; see the file COPYING3.  If not see
    Formal - the caller's formal parameter is passed as an actual argument.
    Constant - a constant is passed as an actual argument.
    Unknown - neither of the above.
-   Integer and real constants are represented as IPA_CONST and Fortran
-   constants are represented as IPA_CONST_REF.  Finally, IPA_CONST_MEMBER_PTR
-   stands for C++ member pointers constants.  */
+   Integer and real constants are represented as IPA_CONST.
+   Finally, IPA_CONST_MEMBER_PTR stands for C++ member pointers constants.  */
 enum jump_func_type
 {
   IPA_UNKNOWN = 0,     /* newly allocated and zeroed jump functions default */
   IPA_CONST,
-  IPA_CONST_REF,
   IPA_CONST_MEMBER_PTR,
   IPA_PASS_THROUGH
 };
@@ -52,13 +50,11 @@ enum jump_func_type
    IPA_CONST_VALUE - simple scalar constant,
    Cval of formal f will have a constant value if all callsites to this
    function have the same constant value passed to f.
-   Integer and real constants are represented as IPA_CONST and Fortran
-   constants are represented as IPA_CONST_REF.  */
+   Integer and real constants are represented as IPA_CONST.  */
 enum ipa_lattice_type
 {
   IPA_BOTTOM,
   IPA_CONST_VALUE,
-  IPA_CONST_VALUE_REF,
   IPA_TOP
 };
 
index 622e6396723c47d56722235b7ff4d0720a602a5e..ab994379f1e5a72495d026ee98b5e9b999fa108f 100644 (file)
@@ -4214,8 +4214,18 @@ tree_function_versioning (tree old_decl, tree new_decl, varray_type tree_map,
        replace_info
          = (struct ipa_replace_map *) VARRAY_GENERIC_PTR (tree_map, i);
        if (replace_info->replace_p)
-         insert_decl_map (&id, replace_info->old_tree,
-                          replace_info->new_tree);
+         {
+           if (TREE_CODE (replace_info->new_tree) == ADDR_EXPR)
+             {
+               tree op = TREE_OPERAND (replace_info->new_tree, 0);
+               while (handled_component_p (op))
+                 op = TREE_OPERAND (op, 0);
+               if (TREE_CODE (op) == VAR_DECL)
+                 add_referenced_var (op);
+             }
+           insert_decl_map (&id, replace_info->old_tree,
+                            replace_info->new_tree);
+         }
       }
   
   DECL_INITIAL (new_decl) = remap_blocks (DECL_INITIAL (id.src_fn), &id);
index 95d4d5ea61e01d41a4d14cc6aba329bceaa24a1b..912d77fd41043431e77ff351ad838bb11db94369 100644 (file)
@@ -2172,6 +2172,40 @@ decl_address_invariant_p (const_tree op)
   return false;
 }
 
+/* Return whether OP is a DECL whose address is interprocedural-invariant.  */
+
+bool
+decl_address_ip_invariant_p (const_tree op)
+{
+  /* The conditions below are slightly less strict than the one in
+     staticp.  */
+
+  switch (TREE_CODE (op))
+    {
+    case LABEL_DECL:
+    case FUNCTION_DECL:
+    case STRING_CST:
+      return true;
+
+    case VAR_DECL:
+      if (((TREE_STATIC (op) || DECL_EXTERNAL (op))
+           && !DECL_DLLIMPORT_P (op))
+          || DECL_THREAD_LOCAL_P (op))
+        return true;
+      break;
+
+    case CONST_DECL:
+      if ((TREE_STATIC (op) || DECL_EXTERNAL (op)))
+        return true;
+      break;
+
+    default:
+      break;
+    }
+
+  return false;
+}
+
 
 /* Return true if T is function-invariant (internal function, does
    not handle arithmetic; that's handled in skip_simple_arithmetic and
index 656fb0a7acfffcb996b22bcd55a88fefc27841a5..487dd9e5962b46d67101157594382da9eaf70a97 100644 (file)
@@ -4868,6 +4868,7 @@ extern tree strip_float_extensions (tree);
 /* In tree.c */
 extern int really_constant_p (const_tree);
 extern bool decl_address_invariant_p (const_tree);
+extern bool decl_address_ip_invariant_p (const_tree);
 extern int int_fits_type_p (const_tree, const_tree);
 #ifndef GENERATOR_FILE
 extern void get_type_static_bounds (const_tree, mpz_t, mpz_t);