diff options
author | Jason Merrill <jason@redhat.com> | 2004-07-14 14:16:48 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2004-07-14 14:16:48 -0400 |
commit | 0c322af34a9bdd8bce4b32a0aab0777580b20b9b (patch) | |
tree | 2cec016794db7f4edc897fa4b5d68c8d7bb1ec15 /gcc | |
parent | 3ac5ea7c80dd6f688952560fc425c6b06d6c3c94 (diff) | |
download | gcc-0c322af34a9bdd8bce4b32a0aab0777580b20b9b.zip gcc-0c322af34a9bdd8bce4b32a0aab0777580b20b9b.tar.gz gcc-0c322af34a9bdd8bce4b32a0aab0777580b20b9b.tar.bz2 |
tree-gimple.c (is_gimple_reg_rhs, [...]): New fns.
* tree-gimple.c (is_gimple_reg_rhs, is_gimple_mem_rhs): New fns.
(rhs_test_for): New fn.
(is_gimple_tmp_rhs): Rename from is_gimple_rhs.
* tree-gimple.h: Declare them.
* gimplify.c (gimplify_modify_expr): Use the new fns.
From-SVN: r84696
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/gimplify.c | 36 | ||||
-rw-r--r-- | gcc/tree-gimple.c | 56 | ||||
-rw-r--r-- | gcc/tree-gimple.h | 13 |
4 files changed, 80 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 59ee70e..1e179dd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-07-13 Jason Merrill <jason@redhat.com> + + * tree-gimple.c (is_gimple_reg_rhs, is_gimple_mem_rhs): New fns. + (rhs_test_for): New fn. + (is_gimple_tmp_rhs): Rename from is_gimple_rhs. + * tree-gimple.h: Declare them. + * gimplify.c (gimplify_modify_expr): Use the new fns. + 2004-07-14 Richard Henderson <rth@redhat.com> * config/arm/arm-protos.h (arm_va_arg): Remove. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 770739a..d1b9618 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -446,7 +446,7 @@ internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal) tree t, mod; char class; - gimplify_expr (&val, pre_p, post_p, is_gimple_rhs, fb_rvalue); + gimplify_expr (&val, pre_p, post_p, is_gimple_tmp_rhs, fb_rvalue); t = lookup_tmp_var (val, is_formal); @@ -2610,7 +2610,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, ctor = build (COMPLEX_EXPR, type, r, i); TREE_OPERAND (*expr_p, 1) = ctor; ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, - is_gimple_rhs, fb_rvalue); + is_gimple_tmp_rhs, fb_rvalue); } } break; @@ -2780,7 +2780,8 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) if (ret == GS_ERROR) return ret; - ret = gimplify_expr (from_p, pre_p, post_p, is_gimple_rhs, fb_rvalue); + ret = gimplify_expr (from_p, pre_p, post_p, + rhs_predicate_for (*to_p), fb_rvalue); if (ret == GS_ERROR) return ret; @@ -2791,33 +2792,10 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value) return ret; /* If the destination is already simple, nothing else needed. */ - if (is_gimple_tmp_var (*to_p)) + if (is_gimple_tmp_var (*to_p) || !want_value) ret = GS_ALL_DONE; else - { - /* 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 temporary. - ie temp = RHS; LHS = temp. - - This way the optimizers can determine that the user variable is - only modified if evaluation of the RHS does not throw. - - FIXME this should be handled by the is_gimple_rhs predicate. */ - - if (aggregate_value_p (TREE_TYPE (*from_p), NULL_TREE)) - /* Don't force a temp of a large aggregate type; the copy could be - arbitrarily expensive. Instead we will generate a V_MAY_DEF for - the assignment. */; - else if (TREE_CODE (*from_p) == CALL_EXPR - || (flag_non_call_exceptions && tree_could_trap_p (*from_p)) - /* If we're dealing with a renamable type, either source or dest - must be a renamed variable. */ - || (is_gimple_reg_type (TREE_TYPE (*from_p)) - && !is_gimple_reg (*to_p))) - gimplify_expr (from_p, pre_p, post_p, is_gimple_val, fb_rvalue); - - ret = want_value ? GS_OK : GS_ALL_DONE; - } + ret = GS_OK; if (want_value) { @@ -3975,7 +3953,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue); *expr_p = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (tmp)), tmp); } - else if ((fallback & fb_rvalue) && is_gimple_rhs (*expr_p)) + else if ((fallback & fb_rvalue) && is_gimple_tmp_rhs (*expr_p)) { #if defined ENABLE_CHECKING if (VOID_TYPE_P (TREE_TYPE (*expr_p))) diff --git a/gcc/tree-gimple.c b/gcc/tree-gimple.c index 97a34a1..193f093 100644 --- a/gcc/tree-gimple.c +++ b/gcc/tree-gimple.c @@ -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" @@ -172,10 +173,10 @@ static inline bool is_gimple_id (tree); /* Validation of GIMPLE expressions. */ -/* Return true if T is a GIMPLE RHS. */ +/* Return true if T is a GIMPLE RHS for an assignment to a temporary. */ bool -is_gimple_rhs (tree t) +is_gimple_tmp_rhs (tree t) { enum tree_code code = TREE_CODE (t); @@ -217,6 +218,57 @@ is_gimple_rhs (tree t) return is_gimple_lvalue (t) || is_gimple_val (t); } +/* Returns true iff T is a valid RHS for an assignment to a renamed user + 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 temporary. + ie temp = RHS; LHS = temp. + + This way the optimizers can determine that the user variable is + only modified if evaluation of the RHS does not throw. */ + if (is_gimple_reg_type (TREE_TYPE (t)) + && TREE_SIDE_EFFECTS (t) + && (TREE_CODE (t) == CALL_EXPR + || (flag_non_call_exceptions && tree_could_trap_p (t)))) + return is_gimple_val (t); + else + /* 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 is_gimple_tmp_rhs (t); +} + +/* 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_tmp_rhs (t); +} + +/* Returns the appropriate RHS predicate for this LHS. */ + +gimple_predicate +rhs_predicate_for (tree lhs) +{ + if (is_gimple_tmp_var (lhs)) + return is_gimple_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. */ diff --git a/gcc/tree-gimple.h b/gcc/tree-gimple.h index 5395c67..32647a0 100644 --- a/gcc/tree-gimple.h +++ b/gcc/tree-gimple.h @@ -39,6 +39,8 @@ extern void annotate_all_with_locus (tree *, location_t); the basic form of the expression, they don't recurse to make sure that underlying nodes are also of the right form. */ +typedef bool (*gimple_predicate)(tree); + /* Returns true iff T is a valid GIMPLE statement. */ extern bool is_gimple_stmt (tree); @@ -59,8 +61,15 @@ extern bool is_gimple_lvalue (tree); extern bool is_gimple_min_invariant (tree); /* Returns true iff T is a GIMPLE rvalue. */ extern bool is_gimple_val (tree); -/* Returns true iff T is a valid rhs for a MODIFY_EXPR. */ -extern bool is_gimple_rhs (tree); +/* Returns true iff T is a valid rhs for a MODIFY_EXPR where the LHS is a + GIMPLE temporary, a renamed user variable, or something else, + respectively. */ +extern bool is_gimple_tmp_rhs (tree); +extern bool is_gimple_reg_rhs (tree); +extern bool is_gimple_mem_rhs (tree); +/* Returns the appropriate one of the above three predicates for the LHS + T. */ +extern gimple_predicate rhs_predicate_for (tree); /* Returns true iff T is a valid if-statement condition. */ extern bool is_gimple_condexpr (tree); |