match.pd: Add tcc_comparison...
authorRichard Biener <rguenther@suse.de>
Thu, 13 Nov 2014 13:58:59 +0000 (13:58 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 13 Nov 2014 13:58:59 +0000 (13:58 +0000)
2014-11-13  Richard Biener  <rguenther@suse.de>

* match.pd: Add tcc_comparison, inverted_tcc_comparison
and inverted_tcc_comparison_with_nans operator lists.
Use tcc_comparison in the truth_valued_p predicate definition.
Restrict logical_inverted_value with bit_xor to integral types.
Build a boolean true for simplifying x |^ !x because of
vector types.  Implement patterns from forward_propagate_comparison
* tree-ssa-forwprop.c (forward_propagate_comparison): Remove.
(get_prop_dest_stmt): Likewise.
(pass_forwprop::execute): Do not call it.
* fold-const.c (fold_unary_loc): Remove the pattern here.

* gcc.dg/tree-ssa/forwprop-28.c: Adjust.

From-SVN: r217496

gcc/ChangeLog
gcc/fold-const.c
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
gcc/tree-ssa-forwprop.c

index 9267d828c9cc81404903587052af4387827996b2..0d2f4db5362ebdce6d00d9041ff1047b411fdef2 100644 (file)
@@ -1,3 +1,16 @@
+2014-11-13  Richard Biener  <rguenther@suse.de>
+
+       * match.pd: Add tcc_comparison, inverted_tcc_comparison
+       and inverted_tcc_comparison_with_nans operator lists.
+       Use tcc_comparison in the truth_valued_p predicate definition.
+       Restrict logical_inverted_value with bit_xor to integral types.
+       Build a boolean true for simplifying x |^ !x because of
+       vector types.  Implement patterns from forward_propagate_comparison
+       * tree-ssa-forwprop.c (forward_propagate_comparison): Remove.
+       (get_prop_dest_stmt): Likewise.
+       (pass_forwprop::execute): Do not call it.
+       * fold-const.c (fold_unary_loc): Remove the pattern here.
+
 2014-11-13  Ilya Verbin  <ilya.verbin@intel.com>
            Andrey Turetskiy  <andrey.turetskiy@intel.com>
 
index a711be9c1064cb40c6c4da9a1b1e4c9e4245afe4..e51abee590c6e532895bc11cc60bd2cfe0e6f18a 100644 (file)
@@ -7938,18 +7938,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
          if (i == count)
            return build_vector (type, elements);
        }
-      else if (COMPARISON_CLASS_P (arg0)
-              && (VECTOR_TYPE_P (type)
-                  || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
-       {
-         tree op_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
-         enum tree_code subcode = invert_tree_comparison (TREE_CODE (arg0),
-                                    HONOR_NANS (TYPE_MODE (op_type)));
-         if (subcode != ERROR_MARK)
-           return build2_loc (loc, subcode, type, TREE_OPERAND (arg0, 0),
-                              TREE_OPERAND (arg0, 1));
-       }
-
 
       return NULL_TREE;
 
index 5a423201183f0af0e412046b1b8871af935788b5..6231d4787f4345661ce31654549896cf70cf996b 100644 (file)
@@ -31,6 +31,14 @@ along with GCC; see the file COPYING3.  If not see
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p)
 
+/* Operator lists.  */
+(define_operator_list tcc_comparison
+  lt   le   eq ne ge   gt   unordered ordered   unlt unle ungt unge uneq ltgt)
+(define_operator_list inverted_tcc_comparison
+  ge   gt   ne eq lt   le   ordered   unordered ge   gt   le   lt   ltgt uneq)
+(define_operator_list inverted_tcc_comparison_with_nans
+  unge ungt ne eq unlt unle ordered   unordered ge   gt   le   lt   ltgt uneq)
+
 
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
@@ -172,7 +180,7 @@ along with GCC; see the file COPYING3.  If not see
 (match truth_valued_p
  @0
  (if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
-(for op (lt le eq ne ge gt truth_and truth_andif truth_or truth_orif truth_xor)
+(for op (tcc_comparison truth_and truth_andif truth_or truth_orif truth_xor)
  (match truth_valued_p
   (op @0 @1)))
 (match truth_valued_p
@@ -187,7 +195,8 @@ along with GCC; see the file COPYING3.  If not see
  (ne truth_valued_p@0 integer_onep)
  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
 (match (logical_inverted_value @0)
- (bit_xor truth_valued_p@0 integer_onep))
+ (bit_xor truth_valued_p@0 integer_onep)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))))
 
 /* X & !X -> 0.  */
 (simplify
@@ -197,7 +206,7 @@ along with GCC; see the file COPYING3.  If not see
 (for op (bit_ior bit_xor)
  (simplify
   (op:c truth_valued_p@0 (logical_inverted_value @0))
-  { build_one_cst (type); }))
+  { constant_boolean_node (true, type); }))
 
 (for bitop (bit_and bit_ior)
      rbitop (bit_ior bit_and)
@@ -632,3 +641,42 @@ along with GCC; see the file COPYING3.  If not see
 (simplify
  (cond (logical_inverted_value truth_valued_p@0) @1 @2)
  (cond @0 @2 @1))
+
+
+/* Simplifications of comparisons.  */
+
+/* We can simplify a logical negation of a comparison to the
+   inverted comparison.  As we cannot compute an expression
+   operator using invert_tree_comparison we have to simulate
+   that with expression code iteration.  */
+(for cmp (tcc_comparison)
+     icmp (inverted_tcc_comparison)
+     ncmp (inverted_tcc_comparison_with_nans)
+ /* Ideally we'd like to combine the following two patterns
+    and handle some more cases by using
+      (logical_inverted_value (cmp @0 @1))
+    here but for that genmatch would need to "inline" that.
+    For now implement what forward_propagate_comparison did.  */
+ (simplify
+  (bit_not (cmp @0 @1))
+  (if (VECTOR_TYPE_P (type)
+       || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))
+   /* Comparison inversion may be impossible for trapping math,
+      invert_tree_comparison will tell us.  But we can't use
+      a computed operator in the replacement tree thus we have
+      to play the trick below.  */
+   (with { enum tree_code ic = invert_tree_comparison
+             (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
+    (if (ic == icmp)
+     (icmp @0 @1))
+    (if (ic == ncmp)
+     (ncmp @0 @1)))))
+ (simplify
+  (bit_xor (cmp @0 @1) integer_onep)
+  (if (INTEGRAL_TYPE_P (type))
+   (with { enum tree_code ic = invert_tree_comparison
+             (cmp, HONOR_NANS (TYPE_MODE (TREE_TYPE (@0)))); }
+    (if (ic == icmp)
+     (icmp @0 @1))
+    (if (ic == ncmp)
+     (ncmp @0 @1))))))
index 5376ce19432324dd7c547754bbdb8dc870bd2fcc..279c1b4a57495b49eec5d3aba748720ea18e0003 100644 (file)
@@ -1,3 +1,7 @@
+2014-11-13  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/tree-ssa/forwprop-28.c: Adjust.
+
 2014-11-12  Alexander Ivchenko  <alexander.ivchenko@intel.com>
 
        * lib/target-supports.exp (error_h): New check.
index 5c945fce41ba89300b244be7529902badd8276b9..1824131086ac71f5e409d0756e81810b2649a87d 100644 (file)
@@ -79,6 +79,11 @@ test_8 (int code)
     oof ();
 }
 
-/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 8 "forwprop1"} } */
+/* ???  This used to check for 8 times transforming the combined conditional
+   to a ordered compare.  But the transform does not trigger if we transform
+   the negated code == 22 compare to code != 22 first.  It turns out if
+   we do that we even generate better code on x86 at least.  */
+
+/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* <" 4 "forwprop1"} } */
 /* { dg-final { cleanup-tree-dump "forwprop1" } } */
 
index feb825394565324cf7112cf669fe4726ae623294..d42dcf891a94927b4725eab8ba11f944fed29ba8 100644 (file)
@@ -233,38 +233,6 @@ fwprop_invalidate_lattice (tree name)
 }
 
 
-/* Get the next statement we can propagate NAME's value into skipping
-   trivial copies.  Returns the statement that is suitable as a
-   propagation destination or NULL_TREE if there is no such one.
-   This only returns destinations in a single-use chain.  FINAL_NAME_P
-   if non-NULL is written to the ssa name that represents the use.  */
-
-static gimple
-get_prop_dest_stmt (tree name, tree *final_name_p)
-{
-  use_operand_p use;
-  gimple use_stmt;
-
-  do {
-    /* If name has multiple uses, bail out.  */
-    if (!single_imm_use (name, &use, &use_stmt))
-      return NULL;
-
-    /* If this is not a trivial copy, we found it.  */
-    if (!gimple_assign_ssa_name_copy_p (use_stmt)
-       || gimple_assign_rhs1 (use_stmt) != name)
-      break;
-
-    /* Continue searching uses of the copy destination.  */
-    name = gimple_assign_lhs (use_stmt);
-  } while (1);
-
-  if (final_name_p)
-    *final_name_p = name;
-
-  return use_stmt;
-}
-
 /* Get the statement we can propagate from into NAME skipping
    trivial copies.  Returns the statement which defines the
    propagation source or NULL_TREE if there is no such one.
@@ -1060,90 +1028,6 @@ forward_propagate_addr_expr (tree name, tree rhs, bool parent_single_use_p)
 }
 
 
-/* Forward propagate the comparison defined in *DEFGSI like
-   cond_1 = x CMP y to uses of the form
-     a_1 = (T')cond_1
-     a_1 = !cond_1
-     a_1 = cond_1 != 0
-   Returns true if stmt is now unused.  Advance DEFGSI to the next
-   statement.  */
-
-static bool
-forward_propagate_comparison (gimple_stmt_iterator *defgsi)
-{
-  gimple stmt = gsi_stmt (*defgsi);
-  tree name = gimple_assign_lhs (stmt);
-  gimple use_stmt;
-  tree tmp = NULL_TREE;
-  gimple_stmt_iterator gsi;
-  enum tree_code code;
-  tree lhs;
-
-  /* Don't propagate ssa names that occur in abnormal phis.  */
-  if ((TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
-       && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
-      || (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME
-        && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs2 (stmt))))
-    goto bailout;
-
-  /* Do not un-cse comparisons.  But propagate through copies.  */
-  use_stmt = get_prop_dest_stmt (name, &name);
-  if (!use_stmt
-      || !is_gimple_assign (use_stmt))
-    goto bailout;
-
-  code = gimple_assign_rhs_code (use_stmt);
-  lhs = gimple_assign_lhs (use_stmt);
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
-    goto bailout;
-
-  /* We can propagate the condition into a statement that
-     computes the logical negation of the comparison result.  */
-  if ((code == BIT_NOT_EXPR
-       && TYPE_PRECISION (TREE_TYPE (lhs)) == 1)
-      || (code == BIT_XOR_EXPR
-         && integer_onep (gimple_assign_rhs2 (use_stmt))))
-    {
-      tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
-      bool nans = HONOR_NANS (TYPE_MODE (type));
-      enum tree_code inv_code;
-      inv_code = invert_tree_comparison (gimple_assign_rhs_code (stmt), nans);
-      if (inv_code == ERROR_MARK)
-       goto bailout;
-
-      tmp = build2 (inv_code, TREE_TYPE (lhs), gimple_assign_rhs1 (stmt),
-                   gimple_assign_rhs2 (stmt));
-    }
-  else
-    goto bailout;
-
-  gsi = gsi_for_stmt (use_stmt);
-  gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (tmp));
-  use_stmt = gsi_stmt (gsi);
-  update_stmt (use_stmt);
-
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "  Replaced '");
-      print_gimple_expr (dump_file, stmt, 0, dump_flags);
-      fprintf (dump_file, "' with '");
-      print_gimple_expr (dump_file, use_stmt, 0, dump_flags);
-      fprintf (dump_file, "'\n");
-    }
-
-  /* When we remove stmt now the iterator defgsi goes off it's current
-     sequence, hence advance it now.  */
-  gsi_next (defgsi);
-
-  /* Remove defining statements.  */
-  return remove_prop_source_from_use (name);
-
-bailout:
-  gsi_next (defgsi);
-  return false;
-}
-
-
 /* Helper function for simplify_gimple_switch.  Remove case labels that
    have values outside the range of the new type.  */
 
@@ -2316,11 +2200,6 @@ pass_forwprop::execute (function *fun)
              else
                gsi_next (&gsi);
            }
-         else if (TREE_CODE_CLASS (code) == tcc_comparison)
-           {
-             if (forward_propagate_comparison (&gsi))
-               cfg_changed = true;
-           }
          else
            gsi_next (&gsi);
        }