+2014-11-09 Richard Biener <rguenther@suse.de>
+
+ * match.pd: Add patterns convering two conversions in a row
+ from fold-const.c.
+ * fold-const.c (fold_unary_loc): Remove them here.
+ * tree-ssa-forwprop.c (combine_conversions): Likewise.
+ * genmatch.c (dt_node::gen_kids): Check whether we may
+ follow SSA use-def chains.
+
2014-11-08 Richard Sandiford <richard.sandiford@arm.com>
* config/aarch64/aarch64.c: Include rtl-iter.h.
constant_boolean_node (false, type));
}
- /* Handle cases of two conversions in a row. */
- if (CONVERT_EXPR_P (op0))
- {
- tree inside_type = TREE_TYPE (TREE_OPERAND (op0, 0));
- tree inter_type = TREE_TYPE (op0);
- int inside_int = INTEGRAL_TYPE_P (inside_type);
- int inside_ptr = POINTER_TYPE_P (inside_type);
- int inside_float = FLOAT_TYPE_P (inside_type);
- int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
- unsigned int inside_prec = TYPE_PRECISION (inside_type);
- int inside_unsignedp = TYPE_UNSIGNED (inside_type);
- int inter_int = INTEGRAL_TYPE_P (inter_type);
- int inter_ptr = POINTER_TYPE_P (inter_type);
- int inter_float = FLOAT_TYPE_P (inter_type);
- int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
- unsigned int inter_prec = TYPE_PRECISION (inter_type);
- int inter_unsignedp = TYPE_UNSIGNED (inter_type);
- int final_int = INTEGRAL_TYPE_P (type);
- int final_ptr = POINTER_TYPE_P (type);
- int final_float = FLOAT_TYPE_P (type);
- int final_vec = TREE_CODE (type) == VECTOR_TYPE;
- unsigned int final_prec = TYPE_PRECISION (type);
- int final_unsignedp = TYPE_UNSIGNED (type);
-
- /* In addition to the cases of two conversions in a row
- handled below, if we are converting something to its own
- type via an object of identical or wider precision, neither
- conversion is needed. */
- if (TYPE_MAIN_VARIANT (inside_type) == TYPE_MAIN_VARIANT (type)
- && (((inter_int || inter_ptr) && final_int)
- || (inter_float && final_float))
- && inter_prec >= final_prec)
- return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
-
- /* Likewise, if the intermediate and initial types are either both
- float or both integer, we don't need the middle conversion if the
- former is wider than the latter and doesn't change the signedness
- (for integers). Avoid this if the final type is a pointer since
- then we sometimes need the middle conversion. Likewise if the
- final type has a precision not equal to the size of its mode. */
- if (((inter_int && inside_int)
- || (inter_float && inside_float)
- || (inter_vec && inside_vec))
- && inter_prec >= inside_prec
- && (inter_float || inter_vec
- || inter_unsignedp == inside_unsignedp)
- && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! final_ptr
- && (! final_vec || inter_prec == inside_prec))
- return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
-
- /* If we have a sign-extension of a zero-extended value, we can
- replace that by a single zero-extension. Likewise if the
- final conversion does not change precision we can drop the
- intermediate conversion. */
- if (inside_int && inter_int && final_int
- && ((inside_prec < inter_prec && inter_prec < final_prec
- && inside_unsignedp && !inter_unsignedp)
- || final_prec == inter_prec))
- return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
-
- /* Two conversions in a row are not needed unless:
- - some conversion is floating-point (overstrict for now), or
- - some conversion is a vector (overstrict for now), or
- - the intermediate type is narrower than both initial and
- final, or
- - the intermediate type and innermost type differ in signedness,
- and the outermost type is wider than the intermediate, or
- - the initial type is a pointer type and the precisions of the
- intermediate and final types differ, or
- - the final type is a pointer type and the precisions of the
- initial and intermediate types differ. */
- if (! inside_float && ! inter_float && ! final_float
- && ! inside_vec && ! inter_vec && ! final_vec
- && (inter_prec >= inside_prec || inter_prec >= final_prec)
- && ! (inside_int && inter_int
- && inter_unsignedp != inside_unsignedp
- && inter_prec < final_prec)
- && ((inter_unsignedp && inter_prec > inside_prec)
- == (final_unsignedp && final_prec > inter_prec))
- && ! (inside_ptr && inter_prec != final_prec)
- && ! (final_ptr && inside_prec != inter_prec)
- && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type)))
- return fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 0));
- }
-
/* Handle (T *)&A.B.C for A being of type T and B and C
living at offset zero. This occurs frequently in
C++ upcasting and then accessing the base. */
else
fprintf (f, "tree %s = gimple_call_arg (def_stmt, %u);\n",
child_opname, i);
- fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
+ fprintf (f, "if ((%s = do_valueize (valueize, %s)))\n",
child_opname, child_opname);
fprintf (f, "{\n");
}
if (exprs_len || fns_len)
{
fprintf (f, "case SSA_NAME:\n");
+ fprintf (f, "if (do_valueize (valueize, %s) != NULL_TREE)\n", kid_opname);
fprintf (f, "{\n");
fprintf (f, "gimple def_stmt = SSA_NAME_DEF_STMT (%s);\n", kid_opname);
(simplify
(paren (paren@1 @0))
@1)
+
+/* Handle cases of two conversions in a row. */
+(for ocvt (convert float fix_trunc)
+ (for icvt (convert float)
+ (simplify
+ (ocvt (icvt@1 @0))
+ (with
+ {
+ tree inside_type = TREE_TYPE (@0);
+ tree inter_type = TREE_TYPE (@1);
+ int inside_int = INTEGRAL_TYPE_P (inside_type);
+ int inside_ptr = POINTER_TYPE_P (inside_type);
+ int inside_float = FLOAT_TYPE_P (inside_type);
+ int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
+ unsigned int inside_prec = TYPE_PRECISION (inside_type);
+ int inside_unsignedp = TYPE_UNSIGNED (inside_type);
+ int inter_int = INTEGRAL_TYPE_P (inter_type);
+ int inter_ptr = POINTER_TYPE_P (inter_type);
+ int inter_float = FLOAT_TYPE_P (inter_type);
+ int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
+ unsigned int inter_prec = TYPE_PRECISION (inter_type);
+ int inter_unsignedp = TYPE_UNSIGNED (inter_type);
+ int final_int = INTEGRAL_TYPE_P (type);
+ int final_ptr = POINTER_TYPE_P (type);
+ int final_float = FLOAT_TYPE_P (type);
+ int final_vec = TREE_CODE (type) == VECTOR_TYPE;
+ unsigned int final_prec = TYPE_PRECISION (type);
+ int final_unsignedp = TYPE_UNSIGNED (type);
+ }
+ /* In addition to the cases of two conversions in a row
+ handled below, if we are converting something to its own
+ type via an object of identical or wider precision, neither
+ conversion is needed. */
+ (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
+ || (GENERIC
+ && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
+ && (((inter_int || inter_ptr) && final_int)
+ || (inter_float && final_float))
+ && inter_prec >= final_prec)
+ (ocvt @0))
+
+ /* Likewise, if the intermediate and initial types are either both
+ float or both integer, we don't need the middle conversion if the
+ former is wider than the latter and doesn't change the signedness
+ (for integers). Avoid this if the final type is a pointer since
+ then we sometimes need the middle conversion. Likewise if the
+ final type has a precision not equal to the size of its mode. */
+ (if (((inter_int && inside_int)
+ || (inter_float && inside_float)
+ || (inter_vec && inside_vec))
+ && inter_prec >= inside_prec
+ && (inter_float || inter_vec
+ || inter_unsignedp == inside_unsignedp)
+ && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
+ && TYPE_MODE (type) == TYPE_MODE (inter_type))
+ && ! final_ptr
+ && (! final_vec || inter_prec == inside_prec))
+ (ocvt @0))
+
+ /* If we have a sign-extension of a zero-extended value, we can
+ replace that by a single zero-extension. Likewise if the
+ final conversion does not change precision we can drop the
+ intermediate conversion. */
+ (if (inside_int && inter_int && final_int
+ && ((inside_prec < inter_prec && inter_prec < final_prec
+ && inside_unsignedp && !inter_unsignedp)
+ || final_prec == inter_prec))
+ (ocvt @0))
+
+ /* Two conversions in a row are not needed unless:
+ - some conversion is floating-point (overstrict for now), or
+ - some conversion is a vector (overstrict for now), or
+ - the intermediate type is narrower than both initial and
+ final, or
+ - the intermediate type and innermost type differ in signedness,
+ and the outermost type is wider than the intermediate, or
+ - the initial type is a pointer type and the precisions of the
+ intermediate and final types differ, or
+ - the final type is a pointer type and the precisions of the
+ initial and intermediate types differ. */
+ (if (! inside_float && ! inter_float && ! final_float
+ && ! inside_vec && ! inter_vec && ! final_vec
+ && (inter_prec >= inside_prec || inter_prec >= final_prec)
+ && ! (inside_int && inter_int
+ && inter_unsignedp != inside_unsignedp
+ && inter_prec < final_prec)
+ && ((inter_unsignedp && inter_prec > inside_prec)
+ == (final_unsignedp && final_prec > inter_prec))
+ && ! (inside_ptr && inter_prec != final_prec)
+ && ! (final_ptr && inside_prec != inter_prec)
+ && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
+ && TYPE_MODE (type) == TYPE_MODE (inter_type)))
+ (ocvt @0))))))
+2014-11-09 Richard Biener <rguenther@suse.de>
+
+ * g++.dg/cpp0x/constexpr-reinterpret1.C: XFAIL.
+ * gcc.dg/tree-ssa/pr21031.c: XFAIL.
+
2014-11-07 Andrew Pinski <apinski@cavium.com>
* gcc.c-torture/execute/20141107-1.c: New testcase.
{
/* I am surprised this is considered a constexpr */
return *((Inner *)4);
- } // { dg-error "reinterpret_cast" }
+ } // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
};
B B::instance;
return 0;
}
-/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1" { xfail *-*-* } } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
tree inside_type = TREE_TYPE (defop0);
tree inter_type = TREE_TYPE (op0);
int inside_int = INTEGRAL_TYPE_P (inside_type);
- int inside_ptr = POINTER_TYPE_P (inside_type);
- int inside_float = FLOAT_TYPE_P (inside_type);
- int inside_vec = TREE_CODE (inside_type) == VECTOR_TYPE;
unsigned int inside_prec = TYPE_PRECISION (inside_type);
int inside_unsignedp = TYPE_UNSIGNED (inside_type);
int inter_int = INTEGRAL_TYPE_P (inter_type);
- int inter_ptr = POINTER_TYPE_P (inter_type);
int inter_float = FLOAT_TYPE_P (inter_type);
- int inter_vec = TREE_CODE (inter_type) == VECTOR_TYPE;
unsigned int inter_prec = TYPE_PRECISION (inter_type);
int inter_unsignedp = TYPE_UNSIGNED (inter_type);
int final_int = INTEGRAL_TYPE_P (type);
- int final_ptr = POINTER_TYPE_P (type);
- int final_float = FLOAT_TYPE_P (type);
- int final_vec = TREE_CODE (type) == VECTOR_TYPE;
unsigned int final_prec = TYPE_PRECISION (type);
- int final_unsignedp = TYPE_UNSIGNED (type);
/* Don't propagate ssa names that occur in abnormal phis. */
if (TREE_CODE (defop0) == SSA_NAME
&& SSA_NAME_OCCURS_IN_ABNORMAL_PHI (defop0))
return 0;
- /* In addition to the cases of two conversions in a row
- handled below, if we are converting something to its own
- type via an object of identical or wider precision, neither
- conversion is needed. */
- if (useless_type_conversion_p (type, inside_type)
- && (((inter_int || inter_ptr) && final_int)
- || (inter_float && final_float))
- && inter_prec >= final_prec)
- {
- gimple_assign_set_rhs1 (stmt, unshare_expr (defop0));
- gimple_assign_set_rhs_code (stmt, TREE_CODE (defop0));
- update_stmt (stmt);
- return remove_prop_source_from_use (op0) ? 2 : 1;
- }
-
- /* Likewise, if the intermediate and initial types are either both
- float or both integer, we don't need the middle conversion if the
- former is wider than the latter and doesn't change the signedness
- (for integers). Avoid this if the final type is a pointer since
- then we sometimes need the middle conversion. Likewise if the
- final type has a precision not equal to the size of its mode. */
- if (((inter_int && inside_int)
- || (inter_float && inside_float)
- || (inter_vec && inside_vec))
- && inter_prec >= inside_prec
- && (inter_float || inter_vec
- || inter_unsignedp == inside_unsignedp)
- && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type))
- && ! final_ptr
- && (! final_vec || inter_prec == inside_prec))
- {
- gimple_assign_set_rhs1 (stmt, defop0);
- update_stmt (stmt);
- return remove_prop_source_from_use (op0) ? 2 : 1;
- }
-
- /* If we have a sign-extension of a zero-extended value, we can
- replace that by a single zero-extension. Likewise if the
- final conversion does not change precision we can drop the
- intermediate conversion. */
- if (inside_int && inter_int && final_int
- && ((inside_prec < inter_prec && inter_prec < final_prec
- && inside_unsignedp && !inter_unsignedp)
- || final_prec == inter_prec))
- {
- gimple_assign_set_rhs1 (stmt, defop0);
- update_stmt (stmt);
- return remove_prop_source_from_use (op0) ? 2 : 1;
- }
-
- /* Two conversions in a row are not needed unless:
- - some conversion is floating-point (overstrict for now), or
- - some conversion is a vector (overstrict for now), or
- - the intermediate type is narrower than both initial and
- final, or
- - the intermediate type and innermost type differ in signedness,
- and the outermost type is wider than the intermediate, or
- - the initial type is a pointer type and the precisions of the
- intermediate and final types differ, or
- - the final type is a pointer type and the precisions of the
- initial and intermediate types differ. */
- if (! inside_float && ! inter_float && ! final_float
- && ! inside_vec && ! inter_vec && ! final_vec
- && (inter_prec >= inside_prec || inter_prec >= final_prec)
- && ! (inside_int && inter_int
- && inter_unsignedp != inside_unsignedp
- && inter_prec < final_prec)
- && ((inter_unsignedp && inter_prec > inside_prec)
- == (final_unsignedp && final_prec > inter_prec))
- && ! (inside_ptr && inter_prec != final_prec)
- && ! (final_ptr && inside_prec != inter_prec)
- && ! (final_prec != GET_MODE_PRECISION (TYPE_MODE (type))
- && TYPE_MODE (type) == TYPE_MODE (inter_type)))
- {
- gimple_assign_set_rhs1 (stmt, defop0);
- update_stmt (stmt);
- return remove_prop_source_from_use (op0) ? 2 : 1;
- }
-
/* A truncation to an unsigned type should be canonicalized as
bitwise and of a mask. */
if (final_int && inter_int && inside_int