Hello,
an incredibly suprising patch: I am adapting yet more fold-const
transformations to vectors... (it varies, the last patch was in forwprop)
I was quite conservative with respect to complex: I didn't want to create
a BIT_NOT_EXPR of a complex.
As an aside, while writing this patch, I noticed the following:
double f(double x){ return -2*x; }
double g(double x){ return 2*-x; }
generates mulsd for f and xorpd+addsd for g, I should probably file a PR
about that, the running time may be similar but it is better to
canonicalize.
2013-06-14 Marc Glisse <marc.gli...@inria.fr>
gcc/
* fold-const.c (negate_expr_p): Handle VECTOR_CST.
(fold_negate_expr): Likewise.
(fold_real_zero_addition_p): Handle vectors.
(fold_binary_loc) <PLUS_EXPR, MINUS_EXPR>: Likewise.
gcc/testsuite/
* gcc.dg/fold-minus-1.c: New testcase.
Bootstrap+testsuite on x86_64-unknown-linux-gnu.
--
Marc Glisse
Index: testsuite/gcc.dg/fold-minus-1.c
===================================================================
--- testsuite/gcc.dg/fold-minus-1.c (revision 0)
+++ testsuite/gcc.dg/fold-minus-1.c (revision 0)
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-gimple" } */
+
+typedef int vec __attribute__((vector_size(2*sizeof(int))));
+
+void f(vec*x,vec*y){
+ *x -= *x / *y * *y;
+}
+void g(vec*x,vec*y,vec*z){
+ *x = -1 - *x;
+ *y = -*y - 1;
+ *z = -*z - 13;
+}
+
+/* { dg-final { scan-tree-dump-times "%" 1 "gimple"} } */
+/* { dg-final { scan-tree-dump-times "~" 2 "gimple"} } */
+/* { dg-final { scan-tree-dump-not "/" "gimple"} } */
+/* { dg-final { scan-tree-dump-not "\\\+" "gimple"} } */
+/* { dg-final { scan-tree-dump "{ -13, -13 }" "gimple"} } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
Property changes on: testsuite/gcc.dg/fold-minus-1.c
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision URL
Added: svn:eol-style
+ native
Index: fold-const.c
===================================================================
--- fold-const.c (revision 200071)
+++ fold-const.c (working copy)
@@ -414,20 +414,34 @@ negate_expr_p (tree t)
case REAL_CST:
/* We want to canonicalize to positive real constants. Pretend
that only negative ones can be easily negated. */
return REAL_VALUE_NEGATIVE (TREE_REAL_CST (t));
case COMPLEX_CST:
return negate_expr_p (TREE_REALPART (t))
&& negate_expr_p (TREE_IMAGPART (t));
+ case VECTOR_CST:
+ {
+ if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))
+ return true;
+
+ int count = TYPE_VECTOR_SUBPARTS (type), i;
+
+ for (i = 0; i < count; i++)
+ if (!negate_expr_p (VECTOR_CST_ELT (t, i)))
+ return false;
+
+ return true;
+ }
+
case COMPLEX_EXPR:
return negate_expr_p (TREE_OPERAND (t, 0))
&& negate_expr_p (TREE_OPERAND (t, 1));
case CONJ_EXPR:
return negate_expr_p (TREE_OPERAND (t, 0));
case PLUS_EXPR:
if (HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type))
|| HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
@@ -553,20 +567,35 @@ fold_negate_expr (location_t loc, tree t
tree ipart = negate_expr (TREE_IMAGPART (t));
if ((TREE_CODE (rpart) == REAL_CST
&& TREE_CODE (ipart) == REAL_CST)
|| (TREE_CODE (rpart) == INTEGER_CST
&& TREE_CODE (ipart) == INTEGER_CST))
return build_complex (type, rpart, ipart);
}
break;
+ case VECTOR_CST:
+ {
+ int count = TYPE_VECTOR_SUBPARTS (type), i;
+ tree *elts = XALLOCAVEC (tree, count);
+
+ for (i = 0; i < count; i++)
+ {
+ elts[i] = fold_negate_expr (loc, VECTOR_CST_ELT (t, i));
+ if (elts[i] == NULL_TREE)
+ return NULL_TREE;
+ }
+
+ return build_vector (type, elts);
+ }
+
case COMPLEX_EXPR:
if (negate_expr_p (t))
return fold_build2_loc (loc, COMPLEX_EXPR, type,
fold_negate_expr (loc, TREE_OPERAND (t, 0)),
fold_negate_expr (loc, TREE_OPERAND (t, 1)));
break;
case CONJ_EXPR:
if (negate_expr_p (t))
return fold_build1_loc (loc, CONJ_EXPR, type,
@@ -6161,23 +6190,26 @@ fold_real_zero_addition_p (const_tree ty
return false;
/* Don't allow the fold with -fsignaling-nans. */
if (HONOR_SNANS (TYPE_MODE (type)))
return false;
/* Allow the fold if zeros aren't signed, or their sign isn't important. */
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
return true;
+ /* In a vector or complex, we would need to check the sign of all zeros. */
+ if (TREE_CODE (addend) != REAL_CST)
+ return false;
+
/* Treat x + -0 as x - 0 and x - -0 as x + 0. */
- if (TREE_CODE (addend) == REAL_CST
- && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
+ if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (addend)))
negate = !negate;
/* The mode has signed zeros, and we have to honor their sign.
In this situation, there is only one case we can return true for.
X - 0 is the same as X unless rounding towards -infinity is
supported. */
return negate && !HONOR_SIGN_DEPENDENT_ROUNDING (TYPE_MODE (type));
}
/* Subroutine of fold() that checks comparisons of built-in math
@@ -10154,53 +10186,53 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) + B -> B - A */
if (TREE_CODE (arg0) == NEGATE_EXPR
&& reorder_operands_p (TREE_OPERAND (arg0, 0), arg1))
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type, arg1),
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
{
/* Convert ~A + 1 to -A. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& integer_onep (arg1))
return fold_build1_loc (loc, NEGATE_EXPR, type,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
/* ~X + X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg0, 0);
STRIP_NOPS (tem);
if (operand_equal_p (tem, arg1, 0))
{
- t1 = build_minus_one_cst (type);
+ t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg1);
}
}
/* X + ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& !TYPE_OVERFLOW_TRAPS (type))
{
tree tem = TREE_OPERAND (arg1, 0);
STRIP_NOPS (tem);
if (operand_equal_p (arg0, tem, 0))
{
- t1 = build_minus_one_cst (type);
+ t1 = build_all_ones_cst (type);
return omit_one_operand_loc (loc, type, t1, arg0);
}
}
/* X + (X / CST) * -CST is X % CST. */
if (TREE_CODE (arg1) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
&& operand_equal_p (arg0,
TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0))
{
@@ -10667,46 +10699,44 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, PLUS_EXPR, type, tmp, arg01);
}
}
/* A - (-B) -> A + B */
if (TREE_CODE (arg1) == NEGATE_EXPR)
return fold_build2_loc (loc, PLUS_EXPR, type, op0,
fold_convert_loc (loc, type,
TREE_OPERAND (arg1, 0)));
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
- && (FLOAT_TYPE_P (type)
- || INTEGRAL_TYPE_P (type))
&& negate_expr_p (arg1)
&& reorder_operands_p (arg0, arg1))
return fold_build2_loc (loc, MINUS_EXPR, type,
fold_convert_loc (loc, type,
negate_expr (arg1)),
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
/* Convert -A - 1 to ~A. */
- if (INTEGRAL_TYPE_P (type)
+ if (TREE_CODE (type) != COMPLEX_TYPE
&& TREE_CODE (arg0) == NEGATE_EXPR
&& integer_onep (arg1)
&& !TYPE_OVERFLOW_TRAPS (type))
return fold_build1_loc (loc, BIT_NOT_EXPR, type,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
/* Convert -1 - A to ~A. */
- if (INTEGRAL_TYPE_P (type)
+ if (TREE_CODE (type) != COMPLEX_TYPE
&& integer_all_onesp (arg0))
return fold_build1_loc (loc, BIT_NOT_EXPR, type, op1);
- /* X - (X / CST) * CST is X % CST. */
- if (INTEGRAL_TYPE_P (type)
+ /* X - (X / Y) * Y is X % Y. */
+ if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
&& TREE_CODE (arg1) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR
&& operand_equal_p (arg0,
TREE_OPERAND (TREE_OPERAND (arg1, 0), 0), 0)
&& operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg1, 0), 1),
TREE_OPERAND (arg1, 1), 0))
return
fold_convert_loc (loc, type,
fold_build2_loc (loc, TRUNC_MOD_EXPR, TREE_TYPE
(arg0),
arg0, TREE_OPERAND (arg1, 1)));