From: Jeff Law Date: Wed, 16 Jun 2004 05:09:41 +0000 (-0600) Subject: fold-const.c (swap_tree_comparison): No longer static. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fd660b1bee7af09cd69d1125cf35e6aa5826234c;p=gcc.git fold-const.c (swap_tree_comparison): No longer static. * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cdea3c05152..027ff23c601 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-06-15 Jeff Law + + * 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 * c-common.c (lang_gimplify_stmt): Remove next_p argument. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 72974d6d06f..91f40543cd0 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 50ac3664de6..7cb9953ad95 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2004-06-15 Jeff Law + + * 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 * g++.dg/abi/bitfield3.C: Add comment.. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c index 328d33d1243..5490537900d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c @@ -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"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c index 5ed66d094a0..6e59dd816ca 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c @@ -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 index 00000000000..40d6676d639 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c @@ -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" } } */ + diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 02380b66361..f1edfa18e18 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -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; diff --git a/gcc/tree.h b/gcc/tree.h index 61808953274..a1db1f049d2 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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);