match.pd: Add patterns convering two conversions in a row from fold-const.c.
authorRichard Biener <rguenther@suse.de>
Sun, 9 Nov 2014 11:27:00 +0000 (11:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sun, 9 Nov 2014 11:27:00 +0000 (11:27 +0000)
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.

* g++.dg/cpp0x/constexpr-reinterpret1.C: XFAIL.
* gcc.dg/tree-ssa/pr21031.c: XFAIL.

From-SVN: r217260

gcc/ChangeLog
gcc/fold-const.c
gcc/genmatch.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
gcc/tree-ssa-forwprop.c

index 4a513935160d8d047f8740fc60d59cfdc5039abd..5f7edb2f69f2e79b4305dd6d675919970e8cfdbd 100644 (file)
@@ -1,3 +1,12 @@
+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.
index c712213444c08e11b6b3bfec6c864051754b4d7a..13faf0c524accaf3375dbd13b81d88a8a69d30f2 100644 (file)
@@ -7692,94 +7692,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
                               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.  */
index e01f7b31e529578335dbc81d917013a25c5e313f..723de193ad5bdf65b7d3cd6ee98ca75a54bde046 100644 (file)
@@ -1615,7 +1615,7 @@ dt_operand::gen_gimple_expr (FILE *f)
       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");
     }
@@ -1726,6 +1726,7 @@ dt_node::gen_kids (FILE *f, bool gimple)
   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);
 
index 1c8b8db4658c74e72a2171e62167e7801350355c..a847e820f6d70602e70544155a6b4c23da52507e 100644 (file)
@@ -319,3 +319,96 @@ along with GCC; see the file COPYING3.  If not see
 (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))))))
index 1a3d6f6f33ebf15a8c232299254ea9ab94853952..f4eb87671ce7bd1e66efe74f900921f1fe1a11bf 100644 (file)
@@ -1,3 +1,8 @@
+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.
index 69db98bc7727a5b282638224be609131c737474b..26c92937f4742564860ba01adf4ae01446a134df 100644 (file)
@@ -18,7 +18,7 @@ public:
   {
     /* I am surprised this is considered a constexpr */
     return *((Inner *)4);
-  } // { dg-error "reinterpret_cast" }
+  } // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
 };
 
 B B::instance;
index df200d564d34dd4e171cd8131bd05a75fc77d172..251b84e82ef63337fdfdad82a5d6f9a76f22d0e8 100644 (file)
@@ -16,5 +16,5 @@ foo (int a)
     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" } } */
index 58f38981e934128344593994b70f935817106f5a..2f4998cdb56eb8809a8dd00551307e4680d6c2da 100644 (file)
@@ -2386,109 +2386,20 @@ combine_conversions (gimple_stmt_iterator *gsi)
       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