diff options
author | Jeffrey A Law <law@cygnus.com> | 2000-03-17 14:40:45 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-03-17 14:40:45 -0800 |
commit | 0a1c58a25ab5df1a3e4596024774641ebae8be2a (patch) | |
tree | 720b4c50b7ea074422601de35cfc7e48ed679e49 /gcc/tree.c | |
parent | f1fd8077fd1260362aa134deefc197948da270f8 (diff) | |
download | gcc-0a1c58a25ab5df1a3e4596024774641ebae8be2a.zip gcc-0a1c58a25ab5df1a3e4596024774641ebae8be2a.tar.gz gcc-0a1c58a25ab5df1a3e4596024774641ebae8be2a.tar.bz2 |
Sibling call optimizations.
Co-Authored-By: Richard Henderson <rth@cygnus.com>
From-SVN: r32612
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 79 |
1 files changed, 79 insertions, 0 deletions
@@ -285,6 +285,9 @@ static void mark_type_hash PARAMS ((void *)); void (*lang_unsave) PARAMS ((tree *)); void (*lang_unsave_expr_now) PARAMS ((tree)); +/* If non-null, a language specific version of safe_for_unsave. */ +int (*lang_safe_for_unsave) PARAMS ((tree)); + /* The string used as a placeholder instead of a source file name for built-in tree nodes. The variable, which is dynamically allocated, should be used; the macro is only used to initialize it. */ @@ -2666,6 +2669,82 @@ unsave_expr_now (expr) return expr; } + +/* Return nonzero if it is safe to unsave EXPR, else return zero. + It is not safe to unsave EXPR if it contains any embedded RTL_EXPRs. */ + +int +safe_for_unsave (expr) + tree expr; +{ + enum tree_code code; + register int i; + int first_rtl; + + if (expr == NULL_TREE) + return 1; + + code = TREE_CODE (expr); + first_rtl = first_rtl_op (code); + switch (code) + { + case RTL_EXPR: + return 0; + + case CALL_EXPR: + if (TREE_OPERAND (expr, 1) + && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST) + { + tree exp = TREE_OPERAND (expr, 1); + while (exp) + { + if (! safe_for_unsave (TREE_VALUE (exp))) + return 0; + exp = TREE_CHAIN (exp); + } + } + break; + + default: + if (lang_safe_for_unsave) + switch ((*lang_safe_for_unsave) (expr)) + { + case -1: + break; + case 0: + return 0; + case 1: + return 1; + default: + abort (); + } + break; + } + + switch (TREE_CODE_CLASS (code)) + { + case 'c': /* a constant */ + case 't': /* a type node */ + case 'x': /* something random, like an identifier or an ERROR_MARK. */ + case 'd': /* A decl node */ + case 'b': /* A block node */ + return 1; + + case 'e': /* an expression */ + case 'r': /* a reference */ + case 's': /* an expression with side effects */ + case '<': /* a comparison expression */ + case '2': /* a binary arithmetic expression */ + case '1': /* a unary arithmetic expression */ + for (i = first_rtl - 1; i >= 0; i--) + if (! safe_for_unsave (TREE_OPERAND (expr, i))) + return 0; + return 1; + + default: + return 0; + } +} /* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size or offset that depends on a field within a record. */ |