More forwprop for vectors
Richard Biener
richard.guenther@gmail.com
Thu Jun 13 08:00:00 GMT 2013
On Thu, Jun 13, 2013 at 8:44 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Wed, 12 Jun 2013, Jeff Law wrote:
>
>>> 2013-06-13 Marc Glisse <marc.glisse@inria.fr>
>>>
>>> * tree-ssa-forwprop.c (simplify_bitwise_binary,
>>> associate_plusminus):
>>> Generalize to complex and vector.
>>> * tree.c (build_all_ones_cst): New function.
>>> * tree.h (build_all_ones_cst): Declare it.
>>
>> This is OK.
>>
>> Extra credit if you create some testcases.
>
>
> While writing the testcase, I fixed a bug in the current code (mix up
> between rhs1 and rhs2 for ~A + 1 -> -A which prevents it from ever
> triggering) and generalized the pattern (A + CST) +- CST -> A + CST to also
> allow '-' (it isn't clear to me why it wasn't handled, did I miss a
> reason?). It passes the bootstrap+testsuite on x86_64-unknown-linux-gnu.
>
> Are you ok with the (A +- CST) +- CST -> A +- CST part?
Yes, that looks fine. Please also update the overall comment before the
cases:
/* Second match patterns that allow contracting a plus-minus pair
irrespective of overflow issues.
(A +- B) - A -> +- B
(A +- B) -+ B -> A
(CST +- A) +- CST -> CST +- A
(A + CST) +- CST -> A + CST
~A + A -> -1
~A + 1 -> -A
A - (A +- B) -> -+ B
A +- (B +- A) -> +- B
CST +- (CST +- A) -> CST +- A
CST +- (A +- CST) -> CST +- A
A + ~A -> -1
you can see that we do handle
CST +- (A +- CST) -> CST +- A
so I cannot think of a reason to not handle the commutated variant.
Thus, ok with the above adjusted.
Thanks,
Richard.
> Extra piece of ChangeLog:
>
> gcc/testsuite/
> * gcc.dg/tree-ssa/forwprop-27.c: New testcase.
>
> --
> Marc Glisse
> Index: tree-ssa-forwprop.c
> ===================================================================
> --- tree-ssa-forwprop.c (revision 200044)
> +++ tree-ssa-forwprop.c (working copy)
> @@ -1971,22 +1971,22 @@ simplify_bitwise_binary (gimple_stmt_ite
> gimple_assign_set_rhs2 (stmt, b);
> gimple_assign_set_rhs_code (stmt, def1_code);
> update_stmt (stmt);
> return true;
> }
> }
>
> /* (a | CST1) & CST2 -> (a & CST2) | (CST1 & CST2). */
> if (code == BIT_AND_EXPR
> && def1_code == BIT_IOR_EXPR
> - && TREE_CODE (arg2) == INTEGER_CST
> - && TREE_CODE (def1_arg2) == INTEGER_CST)
> + && CONSTANT_CLASS_P (arg2)
> + && CONSTANT_CLASS_P (def1_arg2))
> {
> tree cst = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg2),
> arg2, def1_arg2);
> tree tem;
> gimple newop;
> if (integer_zerop (cst))
> {
> gimple_assign_set_rhs1 (stmt, def1_arg1);
> update_stmt (stmt);
> return true;
> @@ -2002,34 +2002,33 @@ simplify_bitwise_binary (gimple_stmt_ite
> gimple_assign_set_rhs_code (stmt, BIT_IOR_EXPR);
> update_stmt (stmt);
> return true;
> }
>
> /* Combine successive equal operations with constants. */
> if ((code == BIT_AND_EXPR
> || code == BIT_IOR_EXPR
> || code == BIT_XOR_EXPR)
> && def1_code == code
> - && TREE_CODE (arg2) == INTEGER_CST
> - && TREE_CODE (def1_arg2) == INTEGER_CST)
> + && CONSTANT_CLASS_P (arg2)
> + && CONSTANT_CLASS_P (def1_arg2))
> {
> tree cst = fold_build2 (code, TREE_TYPE (arg2),
> arg2, def1_arg2);
> gimple_assign_set_rhs1 (stmt, def1_arg1);
> gimple_assign_set_rhs2 (stmt, cst);
> update_stmt (stmt);
> return true;
> }
>
> /* Canonicalize X ^ ~0 to ~X. */
> if (code == BIT_XOR_EXPR
> - && TREE_CODE (arg2) == INTEGER_CST
> && integer_all_onesp (arg2))
> {
> gimple_assign_set_rhs_with_ops (gsi, BIT_NOT_EXPR, arg1, NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> update_stmt (stmt);
> return true;
> }
>
> /* Try simple folding for X op !X, and X op X. */
> res = simplify_bitwise_binary_1 (code, TREE_TYPE (arg1), arg1, arg2);
> @@ -2472,73 +2471,75 @@ associate_plusminus (gimple_stmt_iterato
> && code != def_code)
> {
> /* (A +- B) -+ B -> A. */
> code = TREE_CODE (def_rhs1);
> rhs1 = def_rhs1;
> rhs2 = NULL_TREE;
> gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
> NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> gimple_set_modified (stmt, true);
> }
> - else if (TREE_CODE (rhs2) == INTEGER_CST
> - && TREE_CODE (def_rhs1) == INTEGER_CST)
> + else if (CONSTANT_CLASS_P (rhs2)
> + && CONSTANT_CLASS_P (def_rhs1))
> {
> /* (CST +- A) +- CST -> CST +- A. */
> tree cst = fold_binary (code, TREE_TYPE (rhs1),
> def_rhs1, rhs2);
> if (cst && !TREE_OVERFLOW (cst))
> {
> code = def_code;
> gimple_assign_set_rhs_code (stmt, code);
> rhs1 = cst;
> gimple_assign_set_rhs1 (stmt, rhs1);
> rhs2 = def_rhs2;
> gimple_assign_set_rhs2 (stmt, rhs2);
> gimple_set_modified (stmt, true);
> }
> }
> - else if (TREE_CODE (rhs2) == INTEGER_CST
> - && TREE_CODE (def_rhs2) == INTEGER_CST
> - && def_code == PLUS_EXPR)
> + else if (CONSTANT_CLASS_P (rhs2)
> + && CONSTANT_CLASS_P (def_rhs2))
> {
> - /* (A + CST) +- CST -> A + CST. */
> - tree cst = fold_binary (code, TREE_TYPE (rhs1),
> + /* (A +- CST) +- CST -> A +- CST. */
> + enum tree_code mix = (code == def_code)
> + ? PLUS_EXPR : MINUS_EXPR;
> + tree cst = fold_binary (mix, TREE_TYPE (rhs1),
> def_rhs2, rhs2);
> if (cst && !TREE_OVERFLOW (cst))
> {
> - code = PLUS_EXPR;
> + code = def_code;
> gimple_assign_set_rhs_code (stmt, code);
> rhs1 = def_rhs1;
> gimple_assign_set_rhs1 (stmt, rhs1);
> rhs2 = cst;
> gimple_assign_set_rhs2 (stmt, rhs2);
> gimple_set_modified (stmt, true);
> }
> }
> }
> - else if (def_code == BIT_NOT_EXPR
> - && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
> + else if (def_code == BIT_NOT_EXPR && code == PLUS_EXPR)
> {
> tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
> - if (code == PLUS_EXPR
> - && operand_equal_p (def_rhs1, rhs2, 0))
> + if (operand_equal_p (def_rhs1, rhs2, 0))
> {
> /* ~A + A -> -1. */
> - code = INTEGER_CST;
> - rhs1 = build_int_cst_type (TREE_TYPE (rhs2), -1);
> + rhs1 = build_all_ones_cst (TREE_TYPE (rhs2));
> rhs2 = NULL_TREE;
> + code = TREE_CODE (rhs1);
> gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
> NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> gimple_set_modified (stmt, true);
> }
> - else if (code == PLUS_EXPR
> - && integer_onep (rhs1))
> + else if ((TREE_CODE (TREE_TYPE (rhs2)) != COMPLEX_TYPE
> + && integer_onep (rhs2))
> + || (TREE_CODE (rhs2) == COMPLEX_CST
> + && integer_onep (TREE_REALPART (rhs2))
> + && integer_onep (TREE_IMAGPART (rhs2))))
> {
> /* ~A + 1 -> -A. */
> code = NEGATE_EXPR;
> rhs1 = def_rhs1;
> rhs2 = NULL_TREE;
> gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
> NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> gimple_set_modified (stmt, true);
> }
> }
> @@ -2573,66 +2574,65 @@ associate_plusminus (gimple_stmt_iterato
> {
> /* A +- (B +- A) -> +- B. */
> code = ((code == PLUS_EXPR)
> ? TREE_CODE (def_rhs1) : NEGATE_EXPR);
> rhs1 = def_rhs1;
> rhs2 = NULL_TREE;
> gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
> NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> gimple_set_modified (stmt, true);
> }
> - else if (TREE_CODE (rhs1) == INTEGER_CST
> - && TREE_CODE (def_rhs1) == INTEGER_CST)
> + else if (CONSTANT_CLASS_P (rhs1)
> + && CONSTANT_CLASS_P (def_rhs1))
> {
> /* CST +- (CST +- A) -> CST +- A. */
> tree cst = fold_binary (code, TREE_TYPE (rhs2),
> rhs1, def_rhs1);
> if (cst && !TREE_OVERFLOW (cst))
> {
> code = (code == def_code ? PLUS_EXPR : MINUS_EXPR);
> gimple_assign_set_rhs_code (stmt, code);
> rhs1 = cst;
> gimple_assign_set_rhs1 (stmt, rhs1);
> rhs2 = def_rhs2;
> gimple_assign_set_rhs2 (stmt, rhs2);
> gimple_set_modified (stmt, true);
> }
> }
> - else if (TREE_CODE (rhs1) == INTEGER_CST
> - && TREE_CODE (def_rhs2) == INTEGER_CST)
> + else if (CONSTANT_CLASS_P (rhs1)
> + && CONSTANT_CLASS_P (def_rhs2))
> {
> /* CST +- (A +- CST) -> CST +- A. */
> tree cst = fold_binary (def_code == code
> ? PLUS_EXPR : MINUS_EXPR,
> TREE_TYPE (rhs2),
> rhs1, def_rhs2);
> if (cst && !TREE_OVERFLOW (cst))
> {
> rhs1 = cst;
> gimple_assign_set_rhs1 (stmt, rhs1);
> rhs2 = def_rhs1;
> gimple_assign_set_rhs2 (stmt, rhs2);
> gimple_set_modified (stmt, true);
> }
> }
> }
> - else if (def_code == BIT_NOT_EXPR
> - && INTEGRAL_TYPE_P (TREE_TYPE (rhs2)))
> + else if (def_code == BIT_NOT_EXPR)
> {
> tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
> if (code == PLUS_EXPR
> && operand_equal_p (def_rhs1, rhs1, 0))
> {
> /* A + ~A -> -1. */
> - code = INTEGER_CST;
> - rhs1 = build_int_cst_type (TREE_TYPE (rhs1), -1);
> + rhs1 = build_all_ones_cst (TREE_TYPE (rhs1));
> rhs2 = NULL_TREE;
> + code = TREE_CODE (rhs1);
> gimple_assign_set_rhs_with_ops (gsi, code, rhs1,
> NULL_TREE);
> gcc_assert (gsi_stmt (*gsi) == stmt);
> gimple_set_modified (stmt, true);
> }
> }
> }
> }
>
> out:
> if (gimple_modified_p (stmt))
> Index: tree.c
> ===================================================================
> --- tree.c (revision 200044)
> +++ tree.c (working copy)
> @@ -1636,20 +1636,35 @@ build_one_cst (tree type)
> case COMPLEX_TYPE:
> return build_complex (type,
> build_one_cst (TREE_TYPE (type)),
> build_zero_cst (TREE_TYPE (type)));
>
> default:
> gcc_unreachable ();
> }
> }
>
> +/* Return an integer of type TYPE containing all 1's in as much precision
> as
> + it contains, or a complex or vector whose subparts are such integers.
> */
> +
> +tree
> +build_all_ones_cst (tree type)
> +{
> + if (TREE_CODE (type) == COMPLEX_TYPE)
> + {
> + tree scalar = build_all_ones_cst (TREE_TYPE (type));
> + return build_complex (type, scalar, scalar);
> + }
> + else
> + return build_minus_one_cst (type);
> +}
> +
> /* Return a constant of arithmetic type TYPE which is the
> opposite of the multiplicative identity of the set TYPE. */
>
> tree
> build_minus_one_cst (tree type)
> {
> switch (TREE_CODE (type))
> {
> case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
> case POINTER_TYPE: case REFERENCE_TYPE:
> Index: tree.h
> ===================================================================
> --- tree.h (revision 200044)
> +++ tree.h (working copy)
> @@ -4761,20 +4761,21 @@ extern tree build_vector_stat (tree, tre
> extern tree build_vector_from_ctor (tree, vec<constructor_elt, va_gc> *);
> extern tree build_vector_from_val (tree, tree);
> extern tree build_constructor (tree, vec<constructor_elt, va_gc> *);
> extern tree build_constructor_single (tree, tree, tree);
> extern tree build_constructor_from_list (tree, tree);
> extern tree build_constructor_va (tree, int, ...);
> extern tree build_real_from_int_cst (tree, const_tree);
> extern tree build_complex (tree, tree, tree);
> extern tree build_one_cst (tree);
> extern tree build_minus_one_cst (tree);
> +extern tree build_all_ones_cst (tree);
> extern tree build_zero_cst (tree);
> extern tree build_string (int, const char *);
> extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
> #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
> extern tree build_tree_list_vec_stat (const vec<tree, va_gc>
> *MEM_STAT_DECL);
> #define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
> extern tree build_decl_stat (location_t, enum tree_code,
> tree, tree MEM_STAT_DECL);
> extern tree build_fn_decl (const char *, tree);
> #define build_decl(l,c,t,q) build_decl_stat (l,c,t,q MEM_STAT_INFO)
> Index: testsuite/gcc.dg/tree-ssa/forwprop-27.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/forwprop-27.c (revision 0)
> +++ testsuite/gcc.dg/tree-ssa/forwprop-27.c (revision 0)
> @@ -0,0 +1,40 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O -fdump-tree-forwprop1" } */
> +
> +typedef int V __attribute__((vector_size(2*sizeof(int))));
> +typedef __complex__ int C;
> +
> +void f (V *v1, V *v2){
> + V w1 = *v1;
> + V x1 = ~w1;
> + *v1 = x1 + 1;
> + V w2 = *v2;
> + V x2 = ~w2;
> + *v2 = x2 + w2;
> +}
> +
> +void g (V *v1, V *v2){
> + V c1 = { 5, -10 };
> + V c2 = { 32, 13 };
> + *v1 = (*v1|c1)&c2;
> + *v2 = (*v2^c1)^c2;
> +}
> +
> +void h (C *v1, C *v2){
> + C w = *v2;
> + C x = *v1 - w;
> + *v1 = x + w;
> +}
> +
> +void i (V *v1, V *v2){
> + V c1 = { 5, -10 };
> + V c2 = { 32, 13 };
> + *v1 = (*v1-c1)+c2;
> + *v2 = (c1-*v2)+c2;
> +}
> +
> +/* { dg-final { scan-tree-dump-not "\\\+" "forwprop1"} } */
> +/* { dg-final { scan-tree-dump "{ 0, 4 }" "forwprop1"} } */
> +/* { dg-final { scan-tree-dump "{ 37, -5 }" "forwprop1"} } */
> +/* { dg-final { cleanup-tree-dump "forwprop1" } } */
> +
>
> Property changes on: testsuite/gcc.dg/tree-ssa/forwprop-27.c
> ___________________________________________________________________
> Added: svn:keywords
> + Author Date Id Revision URL
> Added: svn:eol-style
> + native
>
>
More information about the Gcc-patches
mailing list