OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-flow-inline.h
index eef2f43..56edae9 100644 (file)
@@ -1,6 +1,6 @@
 /* Inline functions for tree-flow.h
-   Copyright (C) 2001, 2003, 2005, 2006, 2007, 2008 Free Software
-   Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005, 2006, 2007, 2008, 2010
+   Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -44,20 +44,11 @@ gimple_referenced_vars (const struct function *fun)
   return fun->gimple_df->referenced_vars;
 }
 
-/* Artificial variable used to model the effects of nonlocal
-   variables.  */
-static inline tree
-gimple_nonlocal_all (const struct function *fun)
-{
-  gcc_assert (fun && fun->gimple_df);
-  return fun->gimple_df->nonlocal_all;
-}
-
 /* Artificial variable used for the virtual operand FUD chain.  */
 static inline tree
 gimple_vop (const struct function *fun)
 {
-  gcc_assert (fun && fun->gimple_df);
+  gcc_checking_assert (fun && fun->gimple_df);
   return fun->gimple_df->vop;
 }
 
@@ -75,7 +66,7 @@ first_htab_element (htab_iterator *hti, htab_t table)
       if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
        break;
     } while (++(hti->slot) < hti->limit);
-  
+
   if (hti->slot < hti->limit)
     return *(hti->slot);
   return NULL;
@@ -107,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
@@ -133,18 +134,6 @@ static inline tree
 next_referenced_var (referenced_var_iterator *iter)
 {
   return (tree) next_htab_element (&iter->hti);
-} 
-
-/* Fill up VEC with the variables in the referenced vars hashtable.  */
-
-static inline void
-fill_referenced_var_vec (VEC (tree, heap) **vec)
-{
-  referenced_var_iterator rvi;
-  tree var;
-  *vec = NULL;
-  FOR_EACH_REFERENCED_VAR (var, rvi)
-    VEC_safe_push (tree, heap, *vec, var);
 }
 
 /* Return the variable annotation for T, which must be a _DECL node.
@@ -152,24 +141,8 @@ fill_referenced_var_vec (VEC (tree, heap) **vec)
 static inline var_ann_t
 var_ann (const_tree t)
 {
-  var_ann_t ann;
-
-  if (!t->base.ann)
-    return NULL;
-  ann = (var_ann_t) t->base.ann;
-
-  gcc_assert (ann->common.type == VAR_ANN);
-
-  return ann;
-}
-
-/* Return the variable annotation for T, which must be a _DECL node.
-   Create the variable annotation if it doesn't exist.  */
-static inline var_ann_t
-get_var_ann (tree var)
-{
-  var_ann_t ann = var_ann (var);
-  return (ann) ? ann : create_var_ann (var);
+  const var_ann_t *p = DECL_VAR_ANN_PTR (t);
+  return p ? *p : NULL;
 }
 
 /* Get the number of the next statement uid to be allocated.  */
@@ -193,13 +166,6 @@ inc_gimple_stmt_max_uid (struct function *fn)
   return fn->last_stmt_uid++;
 }
 
-/* Return the annotation type for annotation ANN.  */
-static inline enum tree_ann_type
-ann_type (tree_ann_t ann)
-{
-  return ann->common.type;
-}
-
 /* Return the line number for EXPR, or return -1 if we have no line
    number information for it.  */
 static inline int
@@ -235,7 +201,7 @@ delink_imm_use (ssa_use_operand_t *linknode)
 static inline void
 link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list)
 {
-  /* Link the new node at the head of the list.  If we are in the process of 
+  /* Link the new node at the head of the list.  If we are in the process of
      traversing the list, we won't visit any new nodes added to it.  */
   linknode->prev = list;
   linknode->next = list->next;
@@ -254,10 +220,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_assert (*(linknode->use) == def);
-#endif
+        gcc_checking_assert (*(linknode->use) == def);
       link_imm_use_to_list (linknode, root);
     }
 }
@@ -271,7 +235,7 @@ set_ssa_use_from_ptr (use_operand_p use, tree val)
   link_imm_use (use, val);
 }
 
-/* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring 
+/* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring
    in STMT.  */
 static inline void
 link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, gimple stmt)
@@ -288,7 +252,7 @@ static inline void
 relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old)
 {
   /* The node one had better be in the same list.  */
-  gcc_assert (*(old->use) == *(node->use));
+  gcc_checking_assert (*(old->use) == *(node->use));
   node->prev = old->prev;
   node->next = old->next;
   if (old->prev)
@@ -300,7 +264,7 @@ relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old)
     }
 }
 
-/* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring 
+/* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring
    in STMT.  */
 static inline void
 relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old,
@@ -325,8 +289,6 @@ end_readonly_imm_use_p (const imm_use_iterator *imm)
 static inline use_operand_p
 first_readonly_imm_use (imm_use_iterator *imm, tree var)
 {
-  gcc_assert (TREE_CODE (var) == SSA_NAME);
-
   imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
   imm->imm_use = imm->end_p->next;
 #ifdef ENABLE_CHECKING
@@ -458,12 +420,12 @@ num_imm_uses (const_tree var)
   return num;
 }
 
-/* Return the tree pointed-to by USE.  */ 
+/* Return the tree pointed-to by USE.  */
 static inline tree
 get_use_from_ptr (use_operand_p use)
-{ 
+{
   return *(use->use);
-} 
+}
 
 /* Return the tree pointed-to by DEF.  */
 static inline tree
@@ -543,7 +505,7 @@ gimple_phi_arg_has_location (gimple gs, size_t i)
 static inline gimple_seq
 phi_nodes (const_basic_block bb)
 {
-  gcc_assert (!(bb->flags & BB_RTL));
+  gcc_checking_assert (!(bb->flags & BB_RTL));
   if (!bb->il.gimple)
     return NULL;
   return bb->il.gimple->phi_nodes;
@@ -556,7 +518,7 @@ set_phi_nodes (basic_block bb, gimple_seq seq)
 {
   gimple_stmt_iterator i;
 
-  gcc_assert (!(bb->flags & BB_RTL));
+  gcc_checking_assert (!(bb->flags & BB_RTL));
   bb->il.gimple->phi_nodes = seq;
   if (seq)
     for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
@@ -577,20 +539,17 @@ phi_arg_index_from_use (use_operand_p use)
      pointer arithmetic.  */
 
   phi = USE_STMT (use);
-  gcc_assert (gimple_code (phi) == GIMPLE_PHI);
 
   element = (struct phi_arg_d *)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, 
+  /* 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);
-  gcc_assert (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;
 }
 
@@ -599,10 +558,27 @@ phi_arg_index_from_use (use_operand_p use)
 static inline void
 set_is_used (tree var)
 {
-  var_ann_t ann = get_var_ann (var);
-  ann->used = 1;
+  var_ann_t ann = var_ann (var);
+  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.  */
@@ -616,12 +592,18 @@ is_global_var (const_tree t)
 
 /* Return true if VAR may be aliased.  A variable is considered as
    maybe aliased if it has its address taken by the local TU
-   or possibly by another TU.  */
+   or possibly by another TU and might be modified through a pointer.  */
 
 static inline bool
 may_be_aliased (const_tree var)
 {
-  return (TREE_PUBLIC (var) || DECL_EXTERNAL (var) || TREE_ADDRESSABLE (var));
+  return (TREE_CODE (var) != CONST_DECL
+         && !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var))
+              && TREE_READONLY (var)
+              && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var)))
+         && (TREE_PUBLIC (var)
+             || DECL_EXTERNAL (var)
+             || TREE_ADDRESSABLE (var)));
 }
 
 
@@ -634,9 +616,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;
 }
 
@@ -654,44 +634,6 @@ loop_containing_stmt (gimple stmt)
 }
 
 
-/* Return true if VAR is clobbered by function calls.  */
-static inline bool
-is_call_clobbered (const_tree var)
-{
-  return (is_global_var (var)
-         || (may_be_aliased (var)
-             && pt_solution_includes (&cfun->gimple_df->escaped, var)));
-}
-
-/* Return true if VAR is used by function calls.  */
-static inline bool
-is_call_used (const_tree var)
-{
-  return (is_call_clobbered (var)
-         || (may_be_aliased (var)
-             && pt_solution_includes (&cfun->gimple_df->callused, var)));
-}
-
-/* Return the common annotation for T.  Return NULL if the annotation
-   doesn't already exist.  */
-static inline tree_ann_common_t
-tree_common_ann (const_tree t)
-{
-  /* Watch out static variables with unshared annotations.  */
-  if (DECL_P (t) && TREE_CODE (t) == VAR_DECL)
-    return &var_ann (t)->common;
-  return &t->base.ann->common;
-}
-
-/* Return a common annotation for T.  Create the constant annotation if it
-   doesn't exist.  */
-static inline tree_ann_common_t
-get_tree_common_ann (tree t)
-{
-  tree_ann_common_t ann = tree_common_ann (t);
-  return (ann) ? ann : create_tree_common_ann (t);
-}
-
 /*  -----------------------------------------------------------------------  */
 
 /* The following set of routines are used to iterator over various type of
@@ -709,9 +651,7 @@ static inline use_operand_p
 op_iter_next_use (ssa_op_iter *ptr)
 {
   use_operand_p use_p;
-#ifdef ENABLE_CHECKING
-  gcc_assert (ptr->iter_type == ssa_op_iter_use);
-#endif
+  gcc_checking_assert (ptr->iter_type == ssa_op_iter_use);
   if (ptr->uses)
     {
       use_p = USE_OP_PTR (ptr->uses);
@@ -731,9 +671,7 @@ static inline def_operand_p
 op_iter_next_def (ssa_op_iter *ptr)
 {
   def_operand_p def_p;
-#ifdef ENABLE_CHECKING
-  gcc_assert (ptr->iter_type == ssa_op_iter_def);
-#endif
+  gcc_checking_assert (ptr->iter_type == ssa_op_iter_def);
   if (ptr->defs)
     {
       def_p = DEF_OP_PTR (ptr->defs);
@@ -749,9 +687,7 @@ static inline tree
 op_iter_next_tree (ssa_op_iter *ptr)
 {
   tree val;
-#ifdef ENABLE_CHECKING
-  gcc_assert (ptr->iter_type == ssa_op_iter_tree);
-#endif
+  gcc_checking_assert (ptr->iter_type == ssa_op_iter_tree);
   if (ptr->uses)
     {
       val = USE_OP (ptr->uses);
@@ -791,10 +727,12 @@ 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_assert ((!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
-             && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
+  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)
       && ptr->defs
@@ -817,8 +755,8 @@ op_iter_init (ssa_op_iter *ptr, gimple stmt, int flags)
 static inline use_operand_p
 op_iter_init_use (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  gcc_assert ((flags & SSA_OP_ALL_DEFS) == 0
-             && (flags & SSA_OP_USE));
+  gcc_checking_assert ((flags & SSA_OP_ALL_DEFS) == 0
+                      && (flags & SSA_OP_USE));
   op_iter_init (ptr, stmt, flags);
   ptr->iter_type = ssa_op_iter_use;
   return op_iter_next_use (ptr);
@@ -829,8 +767,8 @@ op_iter_init_use (ssa_op_iter *ptr, gimple stmt, int flags)
 static inline def_operand_p
 op_iter_init_def (ssa_op_iter *ptr, gimple stmt, int flags)
 {
-  gcc_assert ((flags & SSA_OP_ALL_USES) == 0
-             && (flags & SSA_OP_DEF));
+  gcc_checking_assert ((flags & SSA_OP_ALL_USES) == 0
+                      && (flags & SSA_OP_DEF));
   op_iter_init (ptr, stmt, flags);
   ptr->iter_type = ssa_op_iter_def;
   return op_iter_next_def (ptr);
@@ -902,7 +840,7 @@ single_ssa_def_operand (gimple stmt, int flags)
 }
 
 
-/* Return true if there are zero operands in STMT matching the type 
+/* Return true if there are zero operands in STMT matching the type
    given in FLAGS.  */
 static inline bool
 zero_ssa_operands (gimple stmt, int flags)
@@ -922,11 +860,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
@@ -936,7 +877,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);
 }
 
@@ -947,7 +888,7 @@ static inline tree
 single_phi_def (gimple stmt, int flags)
 {
   tree def = PHI_RESULT (stmt);
-  if ((flags & SSA_OP_DEF) && is_gimple_reg (def)) 
+  if ((flags & SSA_OP_DEF) && is_gimple_reg (def))
     return def;
   if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def))
     return def;
@@ -965,10 +906,10 @@ op_iter_init_phiuse (ssa_op_iter *ptr, gimple phi, int flags)
   clear_and_done_ssa_iter (ptr);
   ptr->done = false;
 
-  gcc_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0);
+  gcc_checking_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0);
 
   comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
-    
+
   /* If the PHI node doesn't the operand type we care about, we're done.  */
   if ((flags & comp) == 0)
     {
@@ -994,10 +935,10 @@ op_iter_init_phidef (ssa_op_iter *ptr, gimple phi, int flags)
   clear_and_done_ssa_iter (ptr);
   ptr->done = false;
 
-  gcc_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0);
+  gcc_checking_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0);
 
   comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS);
-    
+
   /* If the PHI node doesn't have the operand type we care about,
      we're done.  */
   if ((flags & comp) == 0)
@@ -1032,15 +973,15 @@ end_imm_use_stmt_traverse (imm_use_iterator *imm)
 
 /* Immediate use traversal of uses within a stmt require that all the
    uses on a stmt be sequentially listed.  This routine is used to build up
-   this sequential list by adding USE_P to the end of the current list 
-   currently delimited by HEAD and LAST_P.  The new LAST_P value is 
+   this sequential list by adding USE_P to the end of the current list
+   currently delimited by HEAD and LAST_P.  The new LAST_P value is
    returned.  */
 
 static inline use_operand_p
-move_use_after_head (use_operand_p use_p, use_operand_p head, 
+move_use_after_head (use_operand_p use_p, use_operand_p head,
                      use_operand_p last_p)
 {
-  gcc_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
+  gcc_checking_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
   /* Skip head when we find it.  */
   if (use_p != head)
     {
@@ -1105,8 +1046,6 @@ link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
 static inline gimple
 first_imm_use_stmt (imm_use_iterator *imm, tree var)
 {
-  gcc_assert (TREE_CODE (var) == SSA_NAME);
-  
   imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
   imm->imm_use = imm->end_p->next;
   imm->next_imm_name = NULL_USE_OPERAND_P;
@@ -1188,27 +1127,13 @@ unmodifiable_var_p (const_tree var)
   return TREE_READONLY (var) && (TREE_STATIC (var) || DECL_EXTERNAL (var));
 }
 
-/* Return true if REF, an ARRAY_REF, has an INDIRECT_REF somewhere in it.  */
-
-static inline bool
-array_ref_contains_indirect_ref (const_tree ref)
-{
-  gcc_assert (TREE_CODE (ref) == ARRAY_REF);
-
-  do {
-    ref = TREE_OPERAND (ref, 0);
-  } while (handled_component_p (ref));
-
-  return TREE_CODE (ref) == INDIRECT_REF;
-}
-
 /* Return true if REF, a handled component reference, has an ARRAY_REF
    somewhere in it.  */
 
 static inline bool
 ref_contains_array_ref (const_tree ref)
 {
-  gcc_assert (handled_component_p (ref));
+  gcc_checking_assert (handled_component_p (ref));
 
   do {
     if (TREE_CODE (ref) == ARRAY_REF)
@@ -1297,4 +1222,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  */