Commit 63b88252 by Richard Henderson Committed by Richard Henderson

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
parent 6c4918da
2004-07-07 Richard Henderson <rth@redhat.com>
* 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 <jakub@redhat.com>
* config/i386/i386.c (override_options): Don't set x86_prefetch_sse
......
......@@ -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)
......
......@@ -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);
......
......@@ -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.
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment