fold-const.c (swap_tree_comparison): No longer static.
authorJeff Law <law@redhat.com>
Wed, 16 Jun 2004 05:09:41 +0000 (23:09 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 16 Jun 2004 05:09:41 +0000 (23:09 -0600)
        * fold-const.c (swap_tree_comparison): No longer static.
        (tree_swap_operands_p): Similarly.  Return true if both operands
        are SSA_NAMEs and the first operand has a higher version number than
        the second operand.
        * tree.h (swap_tree_comparison): Prototype.
        (tree_swap_operands_p): Prototype.
        * tree-ssa-operands.c (get_expr_operands): For commutative
        operators and relational comparisons, canonicalize the
        order of the operands.

        * gcc.dg/tree-ssa/20040615-1.c: New test.
        * gcc.dg/tree-ssa/20030824-1.c: Update expected output to
        be less sensitive to operand ordering.
        * gcc.dg/tree-ssa/20030824-2.c: Likewise.

From-SVN: r83224

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c
gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c
gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c [new file with mode: 0644]
gcc/tree-ssa-operands.c
gcc/tree.h

index cdea3c05152d0d2c925f3225061c5080080c2c45..027ff23c601ad4d669a0083d27d44cbb9683ea95 100644 (file)
@@ -1,3 +1,15 @@
+2004-06-15  Jeff Law  <law@redhat.com>
+
+       * fold-const.c (swap_tree_comparison): No longer static.
+       (tree_swap_operands_p): Similarly.  Return true if both operands
+       are SSA_NAMEs and the first operand has a higher version number than
+       the second operand.
+       * tree.h (swap_tree_comparison): Prototype.
+       (tree_swap_operands_p): Prototype.
+       * tree-ssa-operands.c (get_expr_operands): For commutative
+       operators and relational comparisons, canonicalize the
+       order of the operands.
+
 2004-06-15  Richard Henderson  <rth@redhat.com>
 
        * c-common.c (lang_gimplify_stmt): Remove next_p argument.
index 72974d6d06fb55fe8b205ec9a2d8a4d5f9d33b0f..91f40543cd0704b65ec478b861554f41c71a9663 100644 (file)
@@ -92,7 +92,6 @@ static hashval_t size_htab_hash (const void *);
 static int size_htab_eq (const void *, const void *);
 static tree fold_convert_const (enum tree_code, tree, tree);
 static enum tree_code invert_tree_comparison (enum tree_code, bool);
-static enum tree_code swap_tree_comparison (enum tree_code);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
 static tree combine_comparisons (enum tree_code, enum tree_code,
@@ -132,8 +131,6 @@ static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
 static tree fold_inf_compare (enum tree_code, tree, tree, tree);
 static tree fold_div_compare (enum tree_code, tree, tree, tree);
 static bool reorder_operands_p (tree, tree);
-static bool tree_swap_operands_p (tree, tree, bool);
-
 static tree fold_negate_const (tree, tree);
 static tree fold_not_const (tree, tree);
 static tree fold_relational_const (enum tree_code, tree, tree, tree);
@@ -2119,7 +2116,7 @@ invert_tree_comparison (enum tree_code code, bool honor_nans)
 /* Similar, but return the comparison that results if the operands are
    swapped.  This is safe for floating-point.  */
 
-static enum tree_code
+enum tree_code
 swap_tree_comparison (enum tree_code code)
 {
   switch (code)
@@ -5527,7 +5524,7 @@ reorder_operands_p (tree arg0, tree arg1)
    isn't.  If REORDER is true, only recommend swapping if we can
    evaluate the operands in reverse order.  */
 
-static bool
+bool
 tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
 {
   STRIP_SIGN_NOPS (arg0);
@@ -5574,6 +5571,15 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   if (DECL_P (arg0))
     return 1;
 
+  /* It is preferable to swap two SSA_NAME to ensure a canonical form
+     for commutative and comparison operators.  Ensuring a canonical
+     form allows the optimizers to find additional redundancies without
+     having to explicitly check for both orderings.  */
+  if (TREE_CODE (arg0) == SSA_NAME
+      && TREE_CODE (arg1) == SSA_NAME
+      && SSA_NAME_VERSION (arg0) > SSA_NAME_VERSION (arg1))
+    return 1;
+
   return 0;
 }
 
index 50ac3664de62a8ea8b9d9a5cd446642b6a71b886..7cb9953ad95c9831632fffdc012242162282fea8 100644 (file)
@@ -1,3 +1,10 @@
+2004-06-15  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/20040615-1.c: New test.
+       * gcc.dg/tree-ssa/20030824-1.c: Update expected output to
+       be less sensitive to operand ordering.
+       * gcc.dg/tree-ssa/20030824-2.c: Likewise.
+
 2004-06-16  Danny Smith  <dannysmith@users.sourceforge.net>
 
        * g++.dg/abi/bitfield3.C: Add comment..
index 328d33d12433fbfbcb6101660092f93b65b87073..5490537900dd11955d68ac088de7821820b13fb2 100644 (file)
@@ -19,4 +19,4 @@ int foo (int x, int y)
 }
 
 /* The addition should be optimized into 'y+x'.  */
-/* { dg-final { scan-tree-dump-times "y \\+ x" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\[xy\] \\+ \[xy]" 1 "optimized"} } */
index 5ed66d094a0a69dc1b84d04586b7f6e420270c63..6e59dd816ca31debbfedbcb35b8fffb4eb79d6d4 100644 (file)
@@ -19,4 +19,4 @@ int foo (int x, int y)
 }
 
 /* This function should be optimized into 'return y+x'.  */
-/* { dg-final { scan-tree-dump-times "return y \\+ x" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "return \[xy\] \\+ \[xy\]" 1 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c
new file mode 100644 (file)
index 0000000..40d6676
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-dom1 -fdump-tree-dom2" } */
+  
+void bar1 (void);
+void bar2 (void);
+
+void
+foo (unsigned int a, unsigned int b)
+{
+  if (a >= b)
+    bar1 ();
+  else if (b <= a)
+    bar2 ();
+}
+
+
+/* We do not canonicalize the second conditional immediately after going
+   into SSA form, thus the first dominator pass is unable to remove
+   the useless conditional.   Thus the xfailed test. 
+
+   However, the second conditional is canonicalized before the second
+   dominator optimizer pass and we do want to verify the call to 
+   bar2 was eliminated.  */
+/* { dg-final { scan-tree-dump-times "bar2" 0 "dom1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "bar2" 0 "dom2" } } */
+
index 02380b66361deae1e683e119cbf475a8947f450a..f1edfa18e185c39f6df0bef3a590d036a9854998 100644 (file)
@@ -1235,6 +1235,37 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
       || code == TRUTH_XOR_EXPR
       || code == COMPOUND_EXPR)
     {
+      tree op0 = TREE_OPERAND (expr, 0);
+      tree op1 = TREE_OPERAND (expr, 1);
+
+      /* If it would be profitable to swap the operands, then do so to
+        canonicalize the statement, enabling better optimization.
+
+        By placing canonicalization of such expressions here we
+        transparently keep statements in canonical form, even
+        when the statement is modified.  */
+      if (tree_swap_operands_p (op0, op1, false))
+       {
+         /* For relationals we need to swap the operands and change
+            the code.  */
+         if (code == LT_EXPR
+             || code == GT_EXPR
+             || code == LE_EXPR
+             || code == GE_EXPR)
+           {
+             TREE_SET_CODE (expr, swap_tree_comparison (code));
+             TREE_OPERAND (expr, 0) = op1;
+             TREE_OPERAND (expr, 1) = op0;
+           }
+         
+         /* For a commutative operator we can just swap the operands.  */
+         if (commutative_tree_code (code))
+           {
+             TREE_OPERAND (expr, 0) = op1;
+             TREE_OPERAND (expr, 1) = op0;
+           }
+       }
+
       get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags, prev_vops);
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags, prev_vops);
       return;
index 618089532744d8bd9b25e6abf38698293b3e84ea..a1db1f049d2b2bfd04126a048605f75759705c71 100644 (file)
@@ -3332,6 +3332,9 @@ extern tree build_fold_addr_expr (tree);
 extern tree build_fold_addr_expr_with_type (tree, tree);
 extern tree build_fold_indirect_ref (tree);
 
+extern bool tree_swap_operands_p (tree, tree, bool);
+extern enum tree_code swap_tree_comparison (enum tree_code);
+
 /* In builtins.c */
 extern tree fold_builtin (tree);
 extern enum built_in_function builtin_mathfn_code (tree);