OSDN Git Service

* gengtype.c (adjust_field_rtx_def): Add NOTE_INSN_DELETED_LABEL's
[pf3gnuchains/gcc-fork.git] / gcc / gimple.c
index 4d05c98..7032366 100644 (file)
@@ -1,6 +1,6 @@
 /* Gimple IR support functions.
 
-   Copyright 2007, 2008 Free Software Foundation, Inc.
+   Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
    Contributed by Aldy Hernandez <aldyh@redhat.com>
 
 This file is part of GCC.
@@ -25,10 +25,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "tree.h"
 #include "ggc.h"
-#include "errors.h"
 #include "hard-reg-set.h"
 #include "basic-block.h"
 #include "gimple.h"
+#include "toplev.h"
 #include "diagnostic.h"
 #include "tree-flow.h"
 #include "value-prof.h"
@@ -102,7 +102,6 @@ gss_for_code (enum gimple_code code)
     case GIMPLE_COND:
     case GIMPLE_GOTO:
     case GIMPLE_LABEL:
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
     case GIMPLE_SWITCH:                        return GSS_WITH_OPS;
     case GIMPLE_ASM:                   return GSS_ASM;
     case GIMPLE_BIND:                  return GSS_BIND;
@@ -190,8 +189,6 @@ gimple_size (enum gimple_code code)
       return sizeof (struct gimple_statement_omp_atomic_store);
     case GIMPLE_WITH_CLEANUP_EXPR:
       return sizeof (struct gimple_statement_wce);
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
-      return sizeof (struct gimple_statement_with_ops);
     case GIMPLE_PREDICT:
       return sizeof (struct gimple_statement_base);
     default:
@@ -271,7 +268,7 @@ gimple_build_with_ops_stat (enum gimple_code code, enum tree_code subcode,
 gimple
 gimple_build_return (tree retval)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_RETURN, 0, 1);
+  gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1);
   if (retval)
     gimple_return_set_retval (s, retval);
   return s;
@@ -284,7 +281,7 @@ gimple_build_return (tree retval)
 static inline gimple
 gimple_build_call_1 (tree fn, unsigned nargs)
 {
-  gimple s = gimple_build_with_ops (GIMPLE_CALL, 0, nargs + 3);
+  gimple s = gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK, nargs + 3);
   if (TREE_CODE (fn) == FUNCTION_DECL)
     fn = build_fold_addr_expr (fn);
   gimple_set_op (s, 1, fn);
@@ -544,7 +541,7 @@ gimple_cond_set_condition_from_tree (gimple stmt, tree cond)
 gimple
 gimple_build_label (tree label)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_LABEL, 0, 1);
+  gimple p = gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1);
   gimple_label_set_label (p, label);
   return p;
 }
@@ -554,7 +551,7 @@ gimple_build_label (tree label)
 gimple
 gimple_build_goto (tree dest)
 {
-  gimple p = gimple_build_with_ops (GIMPLE_GOTO, 0, 1);
+  gimple p = gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1);
   gimple_goto_set_dest (p, dest);
   return p;
 }
@@ -600,7 +597,8 @@ gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
   gimple p;
   int size = strlen (string);
 
-  p = gimple_build_with_ops (GIMPLE_ASM, 0, ninputs + noutputs + nclobbers);
+  p = gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
+                            ninputs + noutputs + nclobbers);
 
   p->gimple_asm.ni = ninputs;
   p->gimple_asm.no = noutputs;
@@ -776,7 +774,8 @@ static inline gimple
 gimple_build_switch_1 (unsigned nlabels, tree index, tree default_label)
 {
   /* nlabels + 1 default label + 1 index.  */
-  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, 0, nlabels + 1 + 1);
+  gimple p = gimple_build_with_ops (GIMPLE_SWITCH, ERROR_MARK,
+                                   nlabels + 1 + 1);
   gimple_switch_set_index (p, index);
   gimple_switch_set_default_label (p, default_label);
   return p;
@@ -1040,20 +1039,6 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
 }
 
 
-/* Build a GIMPLE_CHANGE_DYNAMIC_TYPE statement.  TYPE is the new type
-   for the location PTR.  */
-
-gimple
-gimple_build_cdt (tree type, tree ptr)
-{
-  gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, 0, 2);
-  gimple_cdt_set_new_type (p, type);
-  gimple_cdt_set_location (p, ptr);
-
-  return p;
-}
-
-
 /* Build a GIMPLE_OMP_ATOMIC_LOAD statement.  */
 
 gimple
@@ -1458,16 +1443,6 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
        return ret;
       break;
 
-    case GIMPLE_CHANGE_DYNAMIC_TYPE:
-      ret = walk_tree (gimple_cdt_location_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-       return ret;
-
-      ret = walk_tree (gimple_cdt_new_type_ptr (stmt), callback_op, wi, pset);
-      if (ret)
-       return ret;
-      break;
-
     case GIMPLE_ASM:
       ret = walk_gimple_asm (stmt, callback_op, wi);
       if (ret)
@@ -2195,16 +2170,11 @@ gimple_copy (gimple stmt)
       for (i = 0; i < num_ops; i++)
        gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
 
-      /* Clear out SSA operand vectors on COPY.  Note that we cannot
-        call the API functions for setting addresses_taken, stores
-        and loads.  These functions free the previous values, and we
-        cannot do that on COPY as it will affect the original
-        statement.  */
+      /* Clear out SSA operand vectors on COPY.  */
       if (gimple_has_ops (stmt))
        {
          gimple_set_def_ops (copy, NULL);
          gimple_set_use_ops (copy, NULL);
-         copy->gsops.opbase.addresses_taken = NULL;
        }
 
       if (gimple_has_mem_ops (stmt))
@@ -2752,7 +2722,6 @@ is_gimple_stmt (tree t)
     case TRY_FINALLY_EXPR:
     case EH_FILTER_EXPR:
     case CATCH_EXPR:
-    case CHANGE_DYNAMIC_TYPE_EXPR:
     case ASM_EXPR:
     case RESX_EXPR:
     case STATEMENT_LIST:
@@ -2808,13 +2777,7 @@ is_gimple_id (tree t)
 bool
 is_gimple_reg_type (tree type)
 {
-  /* In addition to aggregate types, we also exclude complex types if not
-     optimizing because they can be subject to partial stores in GNU C by
-     means of the __real__ and __imag__ operators and we cannot promote
-     them to total stores (see gimplify_modify_expr_complex_part).  */
-  return !(AGGREGATE_TYPE_P (type)
-          || (TREE_CODE (type) == COMPLEX_TYPE && !optimize));
-
+  return !AGGREGATE_TYPE_P (type);
 }
 
 /* Return true if T is a non-aggregate register variable.  */
@@ -2828,12 +2791,6 @@ is_gimple_reg (tree t)
   if (!is_gimple_variable (t))
     return false;
 
-  /* Complex and vector values must have been put into SSA-like form.
-     That is, no assignments to the individual components.  */
-  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
-      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
-    return DECL_GIMPLE_REG_P (t);
-
   if (!is_gimple_reg_type (TREE_TYPE (t)))
     return false;
 
@@ -2860,6 +2817,12 @@ is_gimple_reg (tree t)
   if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t))
     return false;
 
+  /* Complex and vector values must have been put into SSA-like form.
+     That is, no assignments to the individual components.  */
+  if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE
+      || TREE_CODE (TREE_TYPE (t)) == VECTOR_TYPE)
+    return DECL_GIMPLE_REG_P (t);
+
   return true;
 }
 
@@ -3194,4 +3157,237 @@ 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);
+      while (handled_component_p (rhs))
+       rhs = TREE_OPERAND (rhs, 0);
+      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
+                   && TMR_BASE (rhs) != NULL_TREE
+                  && 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);
+          lhs = gimple_assign_lhs (stmt);
+         if (TREE_CODE (lhs) == TARGET_MEM_REF
+              && TMR_BASE (lhs) != NULL_TREE
+              && TREE_CODE (TMR_BASE (lhs)) == ADDR_EXPR)
+            ret |= visit_addr (stmt, TREE_OPERAND (TMR_BASE (lhs), 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))
+    {
+      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);
+}
+
+/* Helper for gimple_ior_addresses_taken_1.  */
+
+static bool
+gimple_ior_addresses_taken_1 (gimple stmt ATTRIBUTE_UNUSED,
+                             tree addr, void *data)
+{
+  bitmap addresses_taken = (bitmap)data;
+  while (handled_component_p (addr))
+    addr = TREE_OPERAND (addr, 0);
+  if (DECL_P (addr))
+    {
+      bitmap_set_bit (addresses_taken, DECL_UID (addr));
+      return true;
+    }
+  return false;
+}
+
+/* Set the bit for the uid of all decls that have their address taken
+   in STMT in the ADDRESSES_TAKEN bitmap.  Returns true if there
+   were any in this stmt.  */
+
+bool
+gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
+{
+  return walk_stmt_load_store_addr_ops (stmt, addresses_taken, NULL, NULL,
+                                       gimple_ior_addresses_taken_1);
+}
+
 #include "gt-gimple.h"