OSDN Git Service

* tree-flow-inline.h (op_iter_init): Reject GIMPLE_PHI stmts.
[pf3gnuchains/gcc-fork.git] / gcc / tree-flow-inline.h
index 7e93537..b9c5e16 100644 (file)
@@ -98,14 +98,24 @@ next_htab_element (htab_iterator *hti)
   return NULL;
 }
 
+/* Get the variable with uid UID from the list of referenced vars.  */
+
+static inline tree
+referenced_var (unsigned int uid)
+{
+  tree var = referenced_var_lookup (cfun, uid);
+  gcc_assert (var || uid == 0);
+  return var;
+}
+
 /* Initialize ITER to point to the first referenced variable in the
    referenced_vars hashtable, and return that variable.  */
 
 static inline tree
-first_referenced_var (referenced_var_iterator *iter)
+first_referenced_var (struct function *fn, referenced_var_iterator *iter)
 {
   return (tree) first_htab_element (&iter->hti,
-                                   gimple_referenced_vars (cfun));
+                                   gimple_referenced_vars (fn));
 }
 
 /* Return true if we have hit the end of the referenced variables ITER is
@@ -220,10 +230,8 @@ link_imm_use (ssa_use_operand_t *linknode, tree def)
   else
     {
       root = &(SSA_NAME_IMM_USE_NODE (def));
-#ifdef ENABLE_CHECKING
       if (linknode->use)
         gcc_checking_assert (*(linknode->use) == def);
-#endif
       link_imm_use_to_list (linknode, root);
     }
 }
@@ -546,13 +554,11 @@ phi_arg_index_from_use (use_operand_p use)
   root = gimple_phi_arg (phi, 0);
   index = element - root;
 
-#ifdef ENABLE_CHECKING
   /* Make sure the calculation doesn't have any leftover bytes.  If it does,
      then imm_use is likely not the first element in phi_arg_d.  */
-  gcc_assert ((((char *)element - (char *)root)
-              % sizeof (struct phi_arg_d)) == 0
-             && index < gimple_phi_capacity (phi));
-#endif
+  gcc_checking_assert ((((char *)element - (char *)root)
+                       % sizeof (struct phi_arg_d)) == 0
+                      && index < gimple_phi_capacity (phi));
 
  return index;
 }
@@ -563,9 +569,26 @@ static inline void
 set_is_used (tree var)
 {
   var_ann_t ann = get_var_ann (var);
-  ann->used = 1;
+  ann->used = true;
 }
 
+/* Clear VAR's used flag.  */
+
+static inline void
+clear_is_used (tree var)
+{
+  var_ann_t ann = var_ann (var);
+  ann->used = false;
+}
+
+/* Return true if VAR is marked as used.  */
+
+static inline bool
+is_used_p (tree var)
+{
+  var_ann_t ann = var_ann (var);
+  return ann->used;
+}
 
 /* Return true if T (assumed to be a DECL) is a global variable.
    A variable is considered global if its storage is not automatic.  */
@@ -603,9 +626,7 @@ phi_ssa_name_p (const_tree t)
 {
   if (TREE_CODE (t) == SSA_NAME)
     return true;
-#ifdef ENABLE_CHECKING
-  gcc_assert (is_gimple_min_invariant (t));
-#endif
+  gcc_checking_assert (is_gimple_min_invariant (t));
   return false;
 }
 
@@ -716,9 +737,11 @@ clear_and_done_ssa_iter (ssa_op_iter *ptr)
 static inline void
 op_iter_init (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  /* We do not support iterating over virtual defs or uses without
+  /* PHI nodes require a different iterator initialization path.  We
+     do not support iterating over virtual defs or uses without
      iterating over defs or uses at the same time.  */
-  gcc_checking_assert ((!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
+  gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI
+                      && (!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
                       && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
   ptr->defs = (flags & (SSA_OP_DEF|SSA_OP_VDEF)) ? gimple_def_ops (stmt) : NULL;
   if (!(flags & SSA_OP_VDEF)
@@ -847,11 +870,14 @@ num_ssa_operands (gimple stmt, int flags)
   tree t;
   int num = 0;
 
+  gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI);
   FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, flags)
     num++;
   return num;
 }
 
+static inline use_operand_p
+op_iter_init_phiuse (ssa_op_iter *ptr, gimple phi, int flags);
 
 /* Delink all immediate_use information for STMT.  */
 static inline void
@@ -861,7 +887,7 @@ delink_stmt_imm_use (gimple stmt)
    use_operand_p use_p;
 
    if (ssa_operands_active ())
-     FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+     FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
        delink_imm_use (use_p);
 }
 
@@ -965,9 +991,7 @@ static inline use_operand_p
 move_use_after_head (use_operand_p use_p, use_operand_p head,
                      use_operand_p last_p)
 {
-#ifdef ENABLE_CHECKING
-  gcc_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
-#endif
+  gcc_checking_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
   /* Skip head when we find it.  */
   if (use_p != head)
     {
@@ -1208,4 +1232,139 @@ make_ssa_name (tree var, gimple stmt)
   return make_ssa_name_fn (cfun, var, stmt);
 }
 
+/* Returns the base object and a constant BITS_PER_UNIT offset in *POFFSET that
+   denotes the starting address of the memory access EXP.
+   Returns NULL_TREE if the offset is not constant or any component
+   is not BITS_PER_UNIT-aligned.
+   VALUEIZE if non-NULL is used to valueize SSA names.  It should return
+   its argument or a constant if the argument is known to be constant.  */
+
+static inline tree
+get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset,
+                                tree (*valueize) (tree))
+{
+  HOST_WIDE_INT byte_offset = 0;
+
+  /* Compute cumulative byte-offset for nested component-refs and array-refs,
+     and find the ultimate containing object.  */
+  while (1)
+    {
+      switch (TREE_CODE (exp))
+       {
+       case BIT_FIELD_REF:
+         return NULL_TREE;
+
+       case COMPONENT_REF:
+         {
+           tree field = TREE_OPERAND (exp, 1);
+           tree this_offset = component_ref_field_offset (exp);
+           HOST_WIDE_INT hthis_offset;
+
+           if (!this_offset
+               || TREE_CODE (this_offset) != INTEGER_CST
+               || (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+                   % BITS_PER_UNIT))
+             return NULL_TREE;
+
+           hthis_offset = TREE_INT_CST_LOW (this_offset);
+           hthis_offset += (TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field))
+                            / BITS_PER_UNIT);
+           byte_offset += hthis_offset;
+         }
+         break;
+
+       case ARRAY_REF:
+       case ARRAY_RANGE_REF:
+         {
+           tree index = TREE_OPERAND (exp, 1);
+           tree low_bound, unit_size;
+
+           if (valueize
+               && TREE_CODE (index) == SSA_NAME)
+             index = (*valueize) (index);
+
+           /* If the resulting bit-offset is constant, track it.  */
+           if (TREE_CODE (index) == INTEGER_CST
+               && (low_bound = array_ref_low_bound (exp),
+                   TREE_CODE (low_bound) == INTEGER_CST)
+               && (unit_size = array_ref_element_size (exp),
+                   TREE_CODE (unit_size) == INTEGER_CST))
+             {
+               HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
+
+               hindex -= TREE_INT_CST_LOW (low_bound);
+               hindex *= TREE_INT_CST_LOW (unit_size);
+               byte_offset += hindex;
+             }
+           else
+             return NULL_TREE;
+         }
+         break;
+
+       case REALPART_EXPR:
+         break;
+
+       case IMAGPART_EXPR:
+         byte_offset += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (exp)));
+         break;
+
+       case VIEW_CONVERT_EXPR:
+         break;
+
+       case MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (!integer_zerop (TREE_OPERAND (exp, 1)))
+                 {
+                   double_int off = mem_ref_offset (exp);
+                   gcc_assert (off.high == -1 || off.high == 0);
+                   byte_offset += double_int_to_shwi (off);
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+
+       case TARGET_MEM_REF:
+         {
+           tree base = TREE_OPERAND (exp, 0);
+           if (valueize
+               && TREE_CODE (base) == SSA_NAME)
+             base = (*valueize) (base);
+
+           /* Hand back the decl for MEM[&decl, off].  */
+           if (TREE_CODE (base) == ADDR_EXPR)
+             {
+               if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
+                 return NULL_TREE;
+               if (!integer_zerop (TMR_OFFSET (exp)))
+                 {
+                   double_int off = mem_ref_offset (exp);
+                   gcc_assert (off.high == -1 || off.high == 0);
+                   byte_offset += double_int_to_shwi (off);
+                 }
+               exp = TREE_OPERAND (base, 0);
+             }
+           goto done;
+         }
+
+       default:
+         goto done;
+       }
+
+      exp = TREE_OPERAND (exp, 0);
+    }
+done:
+
+  *poffset = byte_offset;
+  return exp;
+}
+
 #endif /* _TREE_FLOW_INLINE_H  */