OSDN Git Service

* tree.c (protected_set_expr_location): New.
[pf3gnuchains/gcc-fork.git] / gcc / gimple.c
index 9e7d921..6e203b7 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
@@ -3142,4 +3180,37 @@ canonicalize_cond_expr_cond (tree t)
   return NULL_TREE;
 }
 
+/* Build call same as STMT but skipping arguments ARGS_TO_SKIP.  */
+gimple
+giple_copy_call_skip_args (gimple stmt, bitmap args_to_skip)
+{
+  int i;
+  tree fn = gimple_call_fn (stmt);
+  int nargs = gimple_call_num_args (stmt);
+  VEC(tree, heap) *vargs = VEC_alloc (tree, heap, nargs);
+  gimple new_stmt;
+
+  for (i = 0; i < nargs; i++)
+    if (!bitmap_bit_p (args_to_skip, i))
+      VEC_quick_push (tree, vargs, gimple_call_arg (stmt, i));
+
+  new_stmt = gimple_build_call_vec (fn, vargs);
+  VEC_free (tree, heap, vargs);
+  if (gimple_call_lhs (stmt))
+    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+
+  gimple_set_block (new_stmt, gimple_block (stmt));
+  if (gimple_has_location (stmt))
+    gimple_set_location (new_stmt, gimple_location (stmt));
+
+  /* Carry all the flags to the new GIMPLE_CALL.  */
+  gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
+  gimple_call_set_tail (new_stmt, gimple_call_tail_p (stmt));
+  gimple_call_set_cannot_inline (new_stmt, gimple_call_cannot_inline_p (stmt));
+  gimple_call_set_return_slot_opt (new_stmt, gimple_call_return_slot_opt_p (stmt));
+  gimple_call_set_from_thunk (new_stmt, gimple_call_from_thunk_p (stmt));
+  gimple_call_set_va_arg_pack (new_stmt, gimple_call_va_arg_pack_p (stmt));
+  return new_stmt;
+}
+
 #include "gt-gimple.h"