* 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
+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
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)
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);
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.
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. */