From: Richard Henderson Date: Wed, 7 Jul 2004 20:16:00 +0000 (-0700) Subject: tree-flow-inline.h (may_propagate_copy): Move... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=63b8825280dc6eac8ff82c577c15831a150c1c40;p=gcc.git tree-flow-inline.h (may_propagate_copy): Move... * tree-flow-inline.h (may_propagate_copy): Move... * tree-ssa-copy.c (may_propagate_copy): ... here. Fail if we attempt to copy between types requiring conversion. * tree-flow.h (may_propagate_copy): Update decl. * tree-ssa-dom.c (cprop_operand): Tidy redundant tests. From-SVN: r84225 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 63de4dcad6a..659885e4d7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-07-07 Richard Henderson + + * tree-flow-inline.h (may_propagate_copy): Move... + * tree-ssa-copy.c (may_propagate_copy): ... here. Fail if we + attempt to copy between types requiring conversion. + * tree-flow.h (may_propagate_copy): Update decl. + * tree-ssa-dom.c (cprop_operand): Tidy redundant tests. + 2004-07-07 Jakub Jelinek * config/i386/i386.c (override_options): Don't set x86_prefetch_sse diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index bda65ca7f5c..e68e63eb8ed 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -467,97 +467,6 @@ is_label_stmt (tree t) return false; } -/* Return true if we may propagate ORIG into DEST, false otherwise. */ -static inline bool -may_propagate_copy (tree dest, tree orig) -{ - /* FIXME. GIMPLE is allowing pointer assignments and comparisons of - pointers that have different alias sets. This means that these - pointers will have different memory tags associated to them. - - If we allow copy propagation in these cases, statements de-referencing - the new pointer will now have a reference to a different memory tag - with potentially incorrect SSA information. - - This was showing up in libjava/java/util/zip/ZipFile.java with code - like: - - struct java.io.BufferedInputStream *T.660; - struct java.io.BufferedInputStream *T.647; - struct java.io.InputStream *is; - struct java.io.InputStream *is.662; - [ ... ] - T.660 = T.647; - is = T.660; <-- This ought to be type-casted - is.662 = is; - - Also, f/name.c exposed a similar problem with a COND_EXPR predicate - that was causing DOM to generate and equivalence with two pointers of - alias-incompatible types: - - struct _ffename_space *n; - struct _ffename *ns; - [ ... ] - if (n == ns) - goto lab; - ... - lab: - return n; - - I think that GIMPLE should emit the appropriate type-casts. For the - time being, blocking copy-propagation in these cases is the safe thing - to do. */ - if (TREE_CODE (dest) == SSA_NAME - && TREE_CODE (orig) == SSA_NAME - && POINTER_TYPE_P (TREE_TYPE (dest)) - && POINTER_TYPE_P (TREE_TYPE (orig))) - { - tree mt_dest = var_ann (SSA_NAME_VAR (dest))->type_mem_tag; - tree mt_orig = var_ann (SSA_NAME_VAR (orig))->type_mem_tag; - if (mt_dest && mt_orig && mt_dest != mt_orig) - return false; - } - - /* If the destination is a SSA_NAME for a virtual operand, then we have - some special cases to handle. */ - if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest)) - { - /* If both operands are SSA_NAMEs referring to virtual operands, then - we can always propagate. */ - if (TREE_CODE (orig) == SSA_NAME) - { - if (!is_gimple_reg (orig)) - return true; - -#ifdef ENABLE_CHECKING - /* If we have one real and one virtual operand, then something has - gone terribly wrong. */ - if (is_gimple_reg (orig)) - abort (); -#endif - } - - /* We have a "copy" from something like a constant into a virtual - operand. Reject these. */ - return false; - } - - /* If ORIG flows in from an abnormal edge, it cannot be propagated. */ - if (TREE_CODE (orig) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)) - return false; - - /* If DEST is an SSA_NAME that flows from an abnormal edge or if it - represents a hard register, then it cannot be replaced. */ - if (TREE_CODE (dest) == SSA_NAME - && (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest) - || DECL_HARD_REGISTER (SSA_NAME_VAR (dest)))) - return false; - - /* Anything else is OK. */ - return true; -} - /* Set the default definition for VAR to DEF. */ static inline void set_default_def (tree var, tree def) diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index aae57bc3cd0..dc4ddb2d7a4 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -591,10 +591,10 @@ extern void debug_dominator_optimization_stats (void); extern void propagate_value (use_operand_p, tree); extern void propagate_tree_value (tree *, tree); extern void replace_exp (use_operand_p, tree); +extern bool may_propagate_copy (tree, tree); /* In tree-flow-inline.h */ static inline int phi_arg_from_edge (tree, edge); -static inline bool may_propagate_copy (tree, tree); static inline bool is_call_clobbered (tree); static inline void mark_call_clobbered (tree); diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index 1f87c1be4bf..5d96fae8e5b 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -55,6 +55,103 @@ Boston, MA 02111-1307, USA. */ APIs defined in this file. */ +/* Return true if we may propagate ORIG into DEST, false otherwise. */ + +bool +may_propagate_copy (tree dest, tree orig) +{ + tree type_d = TREE_TYPE (dest); + tree type_o = TREE_TYPE (orig); + + /* Do not copy between types for which we *do* need a conversion. */ + if (!tree_ssa_useless_type_conversion_1 (type_d, type_o)) + return false; + + /* FIXME. GIMPLE is allowing pointer assignments and comparisons of + pointers that have different alias sets. This means that these + pointers will have different memory tags associated to them. + + If we allow copy propagation in these cases, statements de-referencing + the new pointer will now have a reference to a different memory tag + with potentially incorrect SSA information. + + This was showing up in libjava/java/util/zip/ZipFile.java with code + like: + + struct java.io.BufferedInputStream *T.660; + struct java.io.BufferedInputStream *T.647; + struct java.io.InputStream *is; + struct java.io.InputStream *is.662; + [ ... ] + T.660 = T.647; + is = T.660; <-- This ought to be type-casted + is.662 = is; + + Also, f/name.c exposed a similar problem with a COND_EXPR predicate + that was causing DOM to generate and equivalence with two pointers of + alias-incompatible types: + + struct _ffename_space *n; + struct _ffename *ns; + [ ... ] + if (n == ns) + goto lab; + ... + lab: + return n; + + I think that GIMPLE should emit the appropriate type-casts. For the + time being, blocking copy-propagation in these cases is the safe thing + to do. */ + if (TREE_CODE (dest) == SSA_NAME && TREE_CODE (orig) == SSA_NAME + && POINTER_TYPE_P (type_d) && POINTER_TYPE_P (type_o)) + { + tree mt_dest = var_ann (SSA_NAME_VAR (dest))->type_mem_tag; + tree mt_orig = var_ann (SSA_NAME_VAR (orig))->type_mem_tag; + if (mt_dest && mt_orig && mt_dest != mt_orig) + return false; + } + + /* If the destination is a SSA_NAME for a virtual operand, then we have + some special cases to handle. */ + if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest)) + { + /* If both operands are SSA_NAMEs referring to virtual operands, then + we can always propagate. */ + if (TREE_CODE (orig) == SSA_NAME) + { + if (!is_gimple_reg (orig)) + return true; + +#ifdef ENABLE_CHECKING + /* If we have one real and one virtual operand, then something has + gone terribly wrong. */ + if (is_gimple_reg (orig)) + abort (); +#endif + } + + /* We have a "copy" from something like a constant into a virtual + operand. Reject these. */ + return false; + } + + /* If ORIG flows in from an abnormal edge, it cannot be propagated. */ + if (TREE_CODE (orig) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)) + return false; + + /* If DEST is an SSA_NAME that flows from an abnormal edge or if it + represents a hard register, then it cannot be replaced. */ + if (TREE_CODE (dest) == SSA_NAME + && (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest) + || DECL_HARD_REGISTER (SSA_NAME_VAR (dest)))) + return false; + + /* Anything else is OK. */ + return true; +} + /* Given two SSA_NAMEs, replace the annotations for the one referred to by OP with VAR's annotations. diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 356daacb21c..c03e2bb0675 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -2906,24 +2906,24 @@ cprop_operand (stmt_ann_t ann, use_operand_p op_p, varray_type const_and_copies) val_type = TREE_TYPE (val_type); } - /* Make sure underlying types match before propagating a - constant by converting the constant to the proper type. Note - that convert may return a non-gimple expression, in which case - we ignore this propagation opportunity. */ - if (!lang_hooks.types_compatible_p (op_type, val_type) - && TREE_CODE (val) != SSA_NAME) + /* Make sure underlying types match before propagating a constant by + converting the constant to the proper type. Note that convert may + return a non-gimple expression, in which case we ignore this + propagation opportunity. */ + if (TREE_CODE (val) != SSA_NAME) { - val = fold_convert (TREE_TYPE (op), val); - if (!is_gimple_min_invariant (val) - && TREE_CODE (val) != SSA_NAME) - return false; + if (!lang_hooks.types_compatible_p (op_type, val_type)) + { + val = fold_convert (TREE_TYPE (op), val); + if (!is_gimple_min_invariant (val)) + return false; + } } /* Certain operands are not allowed to be copy propagated due to their interaction with exception handling and some GCC extensions. */ - if (TREE_CODE (val) == SSA_NAME - && !may_propagate_copy (op, val)) + else if (!may_propagate_copy (op, val)) return false; /* Dump details. */