OSDN Git Service

PR c/15498
[pf3gnuchains/gcc-fork.git] / gcc / tree-gimple.c
index 7c992b3..9211a65 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions to analyze and validate GIMPLE trees.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
    Rewritten by Jason Merrill <jason@redhat.com>
 
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tm.h"
 #include "tree.h"
 #include "tree-gimple.h"
+#include "tree-flow.h"
 #include "output.h"
 #include "rtl.h"
 #include "expr.h"
@@ -38,177 +39,163 @@ Boston, MA 02111-1307, USA.  */
 
        http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
 
-   function:
-     FUNCTION_DECL
-       DECL_SAVED_TREE -> block
-   block:
-     BIND_EXPR
-       BIND_EXPR_VARS -> DECL chain
-       BIND_EXPR_BLOCK -> BLOCK
-       BIND_EXPR_BODY -> compound-stmt
-   compound-stmt:
-     COMPOUND_EXPR
-       op0 -> non-compound-stmt
-       op1 -> stmt
-     | EXPR_VEC
-       (or other alternate solution)
-   stmt: compound-stmt | non-compound-stmt
-   non-compound-stmt:
-     block
-     | if-stmt
-     | switch-stmt
-     | jump-stmt
-     | label-stmt
-     | try-stmt
-     | modify-stmt
-     | call-stmt
-   if-stmt:
-     COND_EXPR
-       op0 -> condition
-       op1 -> stmt
-       op2 -> stmt
-   switch-stmt:
-     SWITCH_EXPR
-       op0 -> val
-       op1 -> stmt
-       op2 -> array of case labels (as LABEL_DECLs?)
-         FIXME: add case value info
-       The SWITCH_LABELS (op2) are sorted in ascending order, and the
-       last label in the vector is always the default case.
-   jump-stmt:
-       GOTO_EXPR
-         op0 -> LABEL_DECL | '*' ID
-     | RETURN_EXPR
-         op0 -> NULL_TREE
-             | RESULT_DECL
-             | MODIFY_EXPR -> RESULT_DECL, varname
-     | THROW_EXPR?  do we need/want such a thing for opts, perhaps
-         to generate an ERT_THROW region?  I think so.
-        Hmm...this would only work at the GIMPLE level, where we know that
-          the call args don't have any EH impact.  Perhaps
-          annotation of the CALL_EXPR would work better.
-     | RESX_EXPR
-   label-stmt:
-     LABEL_EXPR
-         op0 -> LABEL_DECL
-     | CASE_LABEL_EXPR
-         CASE_LOW -> val | NULL_TREE
-         CASE_HIGH -> val | NULL_TREE
-        CASE_LABEL -> LABEL_DECL  FIXME
-   try-stmt:
-     TRY_CATCH_EXPR
-       op0 -> stmt
-       op1 -> handler
-     | TRY_FINALLY_EXPR
-       op0 -> stmt
-       op1 -> stmt
-   handler:
-     catch-seq
-     | EH_FILTER_EXPR
-     | stmt
-   modify-stmt:
-     MODIFY_EXPR
-       op0 -> lhs
-       op1 -> rhs
-   call-stmt: CALL_EXPR
-     op0 -> ID | '&' ID
-     op1 -> arglist
-
-   addr-expr-arg : compref | ID
-   lhs: addr-expr-arg | '*' ID | bitfieldref
-   min-lval: ID | '*' ID
-   bitfieldref :
-     BIT_FIELD_REF
-       op0 -> inner_compref
-       op1 -> CONST
-       op2 -> var
-   compref :
-     COMPONENT_REF
-       op0 -> inner_compref
-     | ARRAY_REF
-       op0 -> inner_compref
-       op1 -> val
-       op2 -> val
-       op3 -> val
-     | ARRAY_RANGE_REF
-       op0 -> inner_compref
-       op1 -> val
-       op2 -> val
-       op3 -> val
-     | REALPART_EXPR
-       op0 -> inner_compref
-     | IMAGPART_EXPR
-       op0 -> inner_compref
-
-   inner_compref : compref | min_lval
-     | VIEW_CONVERT_EXPR
-       op0 -> inner_compref
-     | NOP_EXPR
-       op0 -> inner_compref
-     | CONVERT_EXPR
-       op0 -> inner_compref
-
-   condition : val | val relop val
-   val : ID | CONST
-
-   rhs        : varname | CONST
-             | '*' ID
-             | '&' addr-expr-arg
-             | call_expr
-             | unop val
-             | val binop val
-             | '(' cast ')' val
-
-             (cast here stands for all valid C typecasts)
-
-      unop
-             : '+'
-             | '-'
-             | '!'
-             | '~'
-
-      binop
-             : relop | '-'
-             | '+'
-             | '/'
-             | '*'
-             | '%'
-             | '&'
-             | '|'
-             | '<<'
-             | '>>'
-             | '^'
-
-      relop
-             : '<'
-             | '<='
-             | '>'
-             | '>='
-             | '=='
-             | '!='
-
+   function    : FUNCTION_DECL
+                       DECL_SAVED_TREE -> compound-stmt
+
+   compound-stmt: STATEMENT_LIST
+                       members -> stmt
+
+   stmt                : block
+               | if-stmt
+               | switch-stmt
+               | goto-stmt
+               | return-stmt
+               | resx-stmt
+               | label-stmt
+               | try-stmt
+               | modify-stmt
+               | call-stmt
+
+   block       : BIND_EXPR
+                       BIND_EXPR_VARS -> chain of DECLs
+                       BIND_EXPR_BLOCK -> BLOCK
+                       BIND_EXPR_BODY -> compound-stmt
+
+   if-stmt     : COND_EXPR
+                       op0 -> condition
+                       op1 -> compound-stmt
+                       op2 -> compound-stmt
+
+   switch-stmt : SWITCH_EXPR
+                       op0 -> val
+                       op1 -> NULL
+                       op2 -> TREE_VEC of CASE_LABEL_EXPRs
+                           The CASE_LABEL_EXPRs are sorted by CASE_LOW,
+                           and default is last.
+
+   goto-stmt   : GOTO_EXPR
+                       op0 -> LABEL_DECL | val
+
+   return-stmt : RETURN_EXPR
+                       op0 -> return-value
+
+   return-value        : NULL
+               | RESULT_DECL
+               | MODIFY_EXPR
+                       op0 -> RESULT_DECL
+                       op1 -> lhs
+
+   resx-stmt   : RESX_EXPR
+
+   label-stmt  : LABEL_EXPR
+                       op0 -> LABEL_DECL
+
+   try-stmt    : TRY_CATCH_EXPR
+                       op0 -> compound-stmt
+                       op1 -> handler
+               | TRY_FINALLY_EXPR
+                       op0 -> compound-stmt
+                       op1 -> compound-stmt
+
+   handler     : catch-seq
+               | EH_FILTER_EXPR
+               | compound-stmt
+
+   catch-seq   : STATEMENT_LIST
+                       members -> CATCH_EXPR
+
+   modify-stmt : MODIFY_EXPR
+                       op0 -> lhs
+                       op1 -> rhs
+
+   call-stmt   : CALL_EXPR
+                       op0 -> val | OBJ_TYPE_REF
+                       op1 -> call-arg-list
+
+   call-arg-list: TREE_LIST
+                       members -> lhs
+
+   addr-expr-arg: ID
+               | compref
+
+   addressable : addr-expr-arg
+               | indirectref
+
+   with-size-arg: addressable
+               | call-stmt
+
+   indirectref : INDIRECT_REF
+                       op0 -> val
+
+   lhs         : addressable
+               | bitfieldref
+               | WITH_SIZE_EXPR
+                       op0 -> with-size-arg
+                       op1 -> val
+
+   min-lval    : ID
+               | indirectref
+
+   bitfieldref : BIT_FIELD_REF
+                       op0 -> inner-compref
+                       op1 -> CONST
+                       op2 -> var
+
+   compref     : inner-compref
+               | REALPART_EXPR
+                       op0 -> inner-compref
+               | IMAGPART_EXPR
+                       op0 -> inner-compref
+
+   inner-compref: min-lval
+               | COMPONENT_REF
+                       op0 -> inner-compref
+                       op1 -> FIELD_DECL
+                       op2 -> val
+               | ARRAY_REF
+                       op0 -> inner-compref
+                       op1 -> val
+                       op2 -> val
+                       op3 -> val
+               | ARRAY_RANGE_REF
+                       op0 -> inner-compref
+                       op1 -> val
+                       op2 -> val
+                       op3 -> val
+               | VIEW_CONVERT_EXPR
+                       op0 -> inner-compref
+
+   condition   : val
+               | RELOP
+                       op0 -> val
+                       op1 -> val
+
+   val         : ID
+               | CONST
+
+   rhs         : lhs
+               | CONST
+               | call-stmt
+               | ADDR_EXPR
+                       op0 -> addr-expr-arg
+               | UNOP
+                       op0 -> val
+               | BINOP
+                       op0 -> val
+                       op1 -> val
+               | RELOP
+                       op0 -> val
+                       op1 -> val
 */
 
 static inline bool is_gimple_id (tree);
 
 /* Validation of GIMPLE expressions.  */
 
-/* Return nonzero if T is a GIMPLE RHS:
-
-      rhs     : varname | CONST
-             | '*' ID
-             | '&' varname_or_temp
-             | call_expr
-             | unop val
-             | val binop val
-             | '(' cast ')' val
-             | <CONSTRUCTOR <gimple_val ...>>
-
-   The last option is only valid GIMPLE for vector and complex types;
-   aggregate types should have their constructors decomposed.  */
+/* Return true if T is a GIMPLE RHS for an assignment to a temporary.  */
 
 bool
-is_gimple_rhs (tree t)
+is_gimple_formal_tmp_rhs (tree t)
 {
   enum tree_code code = TREE_CODE (t);
 
@@ -217,7 +204,7 @@ is_gimple_rhs (tree t)
     case '1':
     case '2':
     case '<':
-      return 1;
+      return true;
 
     default:
       break;
@@ -233,26 +220,72 @@ is_gimple_rhs (tree t)
     case CALL_EXPR:
     case CONSTRUCTOR:
     case COMPLEX_EXPR:
-      /* FIXME lower VA_ARG_EXPR.  */
-    case VA_ARG_EXPR:
     case INTEGER_CST:
     case REAL_CST:
     case STRING_CST:
     case COMPLEX_CST:
     case VECTOR_CST:
-      return 1;
+    case OBJ_TYPE_REF:
+      return true;
 
     default:
       break;
     }
 
-  if (is_gimple_lvalue (t) || is_gimple_val (t))
-    return 1;
+  return is_gimple_lvalue (t) || is_gimple_val (t);
+}
+
+/* Returns true iff T is a valid RHS for an assignment to a renamed
+   user -- or front-end generated artificial -- variable.  */
+
+bool
+is_gimple_reg_rhs (tree t)
+{
+  /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
+     and the LHS is a user variable, then we need to introduce a formal
+     temporary.  This way the optimizers can determine that the user
+     variable is only modified if evaluation of the RHS does not throw.
+
+     Don't force a temp of a non-renamable type; the copy could be
+     arbitrarily expensive.  Instead we will generate a V_MAY_DEF for
+     the assignment.  */
 
-  return 0;
+  if (is_gimple_reg_type (TREE_TYPE (t))
+      && ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
+         || tree_could_throw_p (t)))
+    return false;
+
+  return is_gimple_formal_tmp_rhs (t);
 }
 
-/* Returns nonzero if T is a valid CONSTRUCTOR component in GIMPLE, either
+/* Returns true iff T is a valid RHS for an assignment to an un-renamed
+   LHS, or for a call argument.  */
+
+bool
+is_gimple_mem_rhs (tree t)
+{
+  /* If we're dealing with a renamable type, either source or dest
+     must be a renamed variable.  */
+  if (is_gimple_reg_type (TREE_TYPE (t)))
+    return is_gimple_val (t);
+  else
+    return is_gimple_formal_tmp_rhs (t);
+}
+
+/* Returns the appropriate RHS predicate for this LHS.  */
+
+gimple_predicate
+rhs_predicate_for (tree lhs)
+{
+  if (is_gimple_formal_tmp_var (lhs))
+    return is_gimple_formal_tmp_rhs;
+  else if (is_gimple_reg (lhs))
+    return is_gimple_reg_rhs;
+  else
+    return is_gimple_mem_rhs;
+}
+
+/* Returns true if T is a valid CONSTRUCTOR component in GIMPLE, either
    a val or another CONSTRUCTOR.  */
 
 bool
@@ -262,24 +295,19 @@ is_gimple_constructor_elt (tree t)
          || TREE_CODE (t) == CONSTRUCTOR);
 }
 
-/*  Return nonzero if T is a valid LHS for a GIMPLE assignment expression.  */
+/*  Return true if T is a valid LHS for a GIMPLE assignment expression.  */
 
 bool
 is_gimple_lvalue (tree t)
 {
-  return (is_gimple_addr_expr_arg (t)
-         || TREE_CODE (t) == INDIRECT_REF
+  return (is_gimple_addressable (t)
+         || TREE_CODE (t) == WITH_SIZE_EXPR
          /* These are complex lvalues, but don't have addresses, so they
             go here.  */
          || TREE_CODE (t) == BIT_FIELD_REF);
 }
 
-
-/*  Return nonzero if T is a GIMPLE condition:
-
-      condexpr
-             : val
-             | val relop val  */
+/*  Return true if T is a GIMPLE condition.  */
 
 bool
 is_gimple_condexpr (tree t)
@@ -288,27 +316,18 @@ is_gimple_condexpr (tree t)
          || TREE_CODE_CLASS (TREE_CODE (t)) == '<');
 }
 
-
-/*  Return nonzero if T is a valid operand for '&':
-
-      varname
-             : arrayref
-             | compref
-             | ID     */
+/*  Return true if T is something whose address can be taken.  */
 
 bool
-is_gimple_addr_expr_arg (tree t)
+is_gimple_addressable (tree t)
 {
-  return (is_gimple_id (t)
-         || TREE_CODE (t) == ARRAY_REF
-         || TREE_CODE (t) == ARRAY_RANGE_REF
-         || TREE_CODE (t) == COMPONENT_REF
+  return (is_gimple_id (t) || handled_component_p (t)
          || TREE_CODE (t) == REALPART_EXPR
          || TREE_CODE (t) == IMAGPART_EXPR
          || TREE_CODE (t) == INDIRECT_REF);
 }
 
-/* Return nonzero if T is function invariant.  Or rather a restricted
+/* Return true if T is function invariant.  Or rather a restricted
    form of function invariant.  */
 
 bool
@@ -331,7 +350,7 @@ is_gimple_min_invariant (tree t)
     }
 }
 
-/* Return nonzero if T looks like a valid GIMPLE statement.  */
+/* Return true if T looks like a valid GIMPLE statement.  */
 
 bool
 is_gimple_stmt (tree t)
@@ -346,7 +365,7 @@ is_gimple_stmt (tree t)
     case BIND_EXPR:
     case COND_EXPR:
       /* These are only valid if they're void.  */
-      return VOID_TYPE_P (TREE_TYPE (t));
+      return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
 
     case SWITCH_EXPR:
     case GOTO_EXPR:
@@ -362,25 +381,19 @@ is_gimple_stmt (tree t)
     case PHI_NODE:
     case STATEMENT_LIST:
       /* These are always void.  */
-      return 1;
-
-    case VA_ARG_EXPR:
-      /* FIXME this should be lowered.  */
-      return 1;
+      return true;
 
-    case COMPOUND_EXPR:
-      /* FIXME should we work harder to make COMPOUND_EXPRs void?  */
     case CALL_EXPR:
     case MODIFY_EXPR:
       /* These are valid regardless of their type.  */
-      return 1;
+      return true;
 
     default:
-      return 0;
+      return false;
     }
 }
 
-/* Return nonzero if T is a variable.  */
+/* Return true if T is a variable.  */
 
 bool
 is_gimple_variable (tree t)
@@ -391,7 +404,7 @@ is_gimple_variable (tree t)
          || TREE_CODE (t) == SSA_NAME);
 }
 
-/*  Return nonzero if T is a GIMPLE identifier (something with an address).  */
+/*  Return true if T is a GIMPLE identifier (something with an address).  */
 
 static inline bool
 is_gimple_id (tree t)
@@ -399,12 +412,12 @@ is_gimple_id (tree t)
   return (is_gimple_variable (t)
          || TREE_CODE (t) == FUNCTION_DECL
          || TREE_CODE (t) == LABEL_DECL
+         || TREE_CODE (t) == CONST_DECL
          /* Allow string constants, since they are addressable.  */
          || TREE_CODE (t) == STRING_CST);
 }
 
-/* Return nonzero if TYPE is a suitable type for a scalar register
-   variable.  */
+/* Return true if TYPE is a suitable type for a scalar register variable.  */
 
 bool
 is_gimple_reg_type (tree type)
@@ -414,7 +427,7 @@ is_gimple_reg_type (tree type)
 }
 
 
-/* Return nonzero if T is a scalar register variable.  */
+/* Return true if T is a scalar register variable.  */
 
 bool
 is_gimple_reg (tree t)
@@ -427,11 +440,39 @@ is_gimple_reg (tree t)
          /* A volatile decl is not acceptable because we can't reuse it as
             needed.  We need to copy it into a temp first.  */
          && ! TREE_THIS_VOLATILE (t)
-         && ! TREE_ADDRESSABLE (t)
          && ! needs_to_live_in_memory (t));
 }
 
-/* Return nonzero if T is a GIMPLE variable whose address is not needed.  */
+/* Returns true if T is a GIMPLE formal temporary variable.  */
+
+bool
+is_gimple_formal_tmp_var (tree t)
+{
+  if (TREE_CODE (t) == SSA_NAME)
+    return true;
+
+  return TREE_CODE (t) == VAR_DECL && DECL_GIMPLE_FORMAL_TEMP_P (t);
+}
+
+/* Returns true if T is a GIMPLE formal temporary register variable.  */
+
+bool
+is_gimple_formal_tmp_reg (tree t)
+{
+  /* The intent of this is to get hold of a value that won't change.
+     An SSA_NAME qualifies no matter if its of a user variable or not.  */
+  if (TREE_CODE (t) == SSA_NAME)
+    return true;
+
+  /* We don't know the lifetime characteristics of user variables.  */
+  if (!is_gimple_formal_tmp_var (t))
+    return false;
+
+  /* Finally, it must be capable of being placed in a register.  */
+  return is_gimple_reg (t);
+}
+
+/* Return true if T is a GIMPLE variable whose address is not needed.  */
 
 bool
 is_gimple_non_addressable (tree t)
@@ -439,13 +480,10 @@ is_gimple_non_addressable (tree t)
   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
 
-  return (is_gimple_variable (t)
-         && ! TREE_ADDRESSABLE (t)
-         && ! needs_to_live_in_memory (t));
+  return (is_gimple_variable (t) && ! needs_to_live_in_memory (t));
 }
 
-/*  Return nonzero if T is a GIMPLE rvalue, i.e. an identifier or a
-    constant.  */
+/* Return true if T is a GIMPLE rvalue, i.e. an identifier or a constant.  */
 
 bool
 is_gimple_val (tree t)
@@ -454,7 +492,7 @@ is_gimple_val (tree t)
   if (is_gimple_variable (t)
       && is_gimple_reg_type (TREE_TYPE (t))
       && !is_gimple_reg (t))
-    return 0;
+    return false;
 
   /* FIXME make these decls.  That can happen only when we expose the
      entire landing-pad construct at the tree level.  */
@@ -465,12 +503,7 @@ is_gimple_val (tree t)
 }
 
 
-/*  Return true if T is a GIMPLE minimal lvalue, of the form
-
-    min_lval: ID | '(' '*' ID ')'
-
-    This never actually appears in the original SIMPLE grammar, but is
-    repeated in several places.  */
+/* Return true if T is a GIMPLE minimal lvalue.  */
 
 bool
 is_gimple_min_lval (tree t)
@@ -479,8 +512,7 @@ is_gimple_min_lval (tree t)
          || TREE_CODE (t) == INDIRECT_REF);
 }
 
-/*  Return nonzero if T is a typecast operation of the form
-    '(' cast ')' val.  */
+/* Return true if T is a typecast operation.  */
 
 bool
 is_gimple_cast (tree t)
@@ -493,6 +525,14 @@ is_gimple_cast (tree t)
           || TREE_CODE (t) == FIX_ROUND_EXPR);
 }
 
+/* Return true if T is a valid op0 of a CALL_EXPR.  */
+
+bool
+is_gimple_call_addr (tree t)
+{
+  return (TREE_CODE (t) == OBJ_TYPE_REF
+         || is_gimple_val (t));
+}
 
 /* If T makes a function call, return the corresponding CALL_EXPR operand.
    Otherwise, return NULL_TREE.  */
@@ -500,90 +540,15 @@ is_gimple_cast (tree t)
 tree
 get_call_expr_in (tree t)
 {
+  if (TREE_CODE (t) == MODIFY_EXPR)
+    t = TREE_OPERAND (t, 1);
+  if (TREE_CODE (t) == WITH_SIZE_EXPR)
+    t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CALL_EXPR)
     return t;
-  else if (TREE_CODE (t) == MODIFY_EXPR
-          && TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
-    return TREE_OPERAND (t, 1);
-  else if (TREE_CODE (t) == RETURN_EXPR
-           && TREE_OPERAND (t, 0)
-          && TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
-          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == CALL_EXPR)
-    return TREE_OPERAND (TREE_OPERAND (t, 0), 1);
-
   return NULL_TREE;
 }
 
-
-/* Given an _EXPR TOP, reorganize all of the nested _EXPRs with the same
-   code so that they only appear as the second operand.  This should only
-   be used for tree codes which are truly associative, such as
-   COMPOUND_EXPR and TRUTH_ANDIF_EXPR.  Arithmetic is not associative
-   enough, due to the limited precision of arithmetic data types.
-
-   This transformation is conservative; the operand 0 of a matching tree
-   node will only change if it is also a matching node.  */
-
-tree
-right_assocify_expr (tree top)
-{
-  tree *p = &top;
-  enum tree_code code = TREE_CODE (*p);
-  while (TREE_CODE (*p) == code)
-    {
-      tree cur = *p;
-      tree lhs = TREE_OPERAND (cur, 0);
-      if (TREE_CODE (lhs) == code)
-       {
-         /* There's a left-recursion.  If we have ((a, (b, c)), d), we
-            want to rearrange to (a, (b, (c, d))).  */
-         tree *q;
-
-         /* Replace cur with the lhs; move (a, *) up.  */
-         *p = lhs;
-
-         if (code == COMPOUND_EXPR)
-           {
-             /* We need to give (b, c) the type of c; previously lhs had
-                the type of b.  */
-             TREE_TYPE (lhs) = TREE_TYPE (cur);
-             if (TREE_SIDE_EFFECTS (cur))
-               TREE_SIDE_EFFECTS (lhs) = 1;
-           }
-
-         /* Walk through the op1 chain from there until we find something
-            with a different code.  In this case, c.  */
-         for (q = &TREE_OPERAND (lhs, 1); TREE_CODE (*q) == code;
-              q = &TREE_OPERAND (*q, 1))
-           TREE_TYPE (*q) = TREE_TYPE (cur);
-
-         /* Change (*, d) into (c, d).  */
-         TREE_OPERAND (cur, 0) = *q;
-
-         /* And plug it in where c used to be.  */
-         *q = cur;
-       }
-      else
-       p = &TREE_OPERAND (cur, 1);
-    }
-  return top;
-}
-
-/* Normalize the statement TOP.  If it is a COMPOUND_EXPR, reorganize it so
-   that we can traverse it without recursion.  If it is null, replace it
-   with a nop.  */
-
-tree
-rationalize_compound_expr (tree top)
-{
-  if (top == NULL_TREE)
-    top = build_empty_stmt ();
-  else if (TREE_CODE (top) == COMPOUND_EXPR)
-    top = right_assocify_expr (top);
-
-  return top;
-}
-
 /* Given a memory reference expression, return the base address.  Note that,
    in contrast with get_base_var, this will not recurse inside INDIRECT_REF
    expressions.  Therefore, given the reference PTR->FIELD, this function
@@ -592,27 +557,19 @@ rationalize_compound_expr (tree top)
 tree
 get_base_address (tree t)
 {
-  do
-    {
-      if (SSA_VAR_P (t)
-         || TREE_CODE (t) == STRING_CST
-         || TREE_CODE (t) == CONSTRUCTOR
-         || TREE_CODE (t) == INDIRECT_REF)
-       return t;
-
-      if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
-       t = TREE_OPERAND (t, 0);
-      else if (handled_component_p (t))
-       t = get_base_address (TREE_OPERAND (t, 0));
-      else
-       return NULL_TREE;
-    }
-  while (t);
-
-  return t;
+  while (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR
+        || handled_component_p (t))
+    t = TREE_OPERAND (t, 0);
+  
+  if (SSA_VAR_P (t)
+      || TREE_CODE (t) == STRING_CST
+      || TREE_CODE (t) == CONSTRUCTOR
+      || TREE_CODE (t) == INDIRECT_REF)
+    return t;
+  else
+    return NULL_TREE;
 }
 
-
 void
 recalculate_side_effects (tree t)
 {
@@ -628,7 +585,6 @@ recalculate_side_effects (tree t)
        case INIT_EXPR:
        case MODIFY_EXPR:
        case VA_ARG_EXPR:
-       case RTL_EXPR:
        case PREDECREMENT_EXPR:
        case PREINCREMENT_EXPR:
        case POSTDECREMENT_EXPR: