Hi Richard,
Thanks for your review and useful comments.
I will move the future optimization patterns with all the conditions
present in fold-const or builtins file as per your suggestions.
Please find attached the patch as per your comments.
Please review the patch and let me know if any further modifications
are required.
The last pattern has been removed due to the discussions over it
and a regression it caused.
================================================
+/* Fold X & (X ^ Y) as X & ~Y. */
+(simplify
+ (bit_and:c (convert? @0) (convert? (bit_xor:c @0 @1)))
+ (bit_and (convert @0) (convert (bit_not @1))))
================================================
FAIL: gcc.dg/tree-ssa/vrp47.c scan-tree-dump-times vrp2 " & 1;" 0
FAIL: gcc.dg/tree-ssa/vrp59.c scan-tree-dump-not vrp1 " & 3;"
Thanks,
Naveen
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5d8822f..8889c39 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -9192,26 +9192,6 @@ fold_binary_loc (location_t loc,
return NULL_TREE;
case PLUS_EXPR:
- if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
- {
- /* 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))
- {
- tree cst0 = TREE_OPERAND (TREE_OPERAND (arg1, 0), 1);
- tree cst1 = TREE_OPERAND (arg1, 1);
- tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (cst1),
- cst1, cst0);
- if (sum && integer_zerop (sum))
- return fold_convert_loc (loc, type,
- fold_build2_loc (loc, TRUNC_MOD_EXPR,
- TREE_TYPE (arg0), arg0,
- cst0));
- }
- }
-
/* Handle (A1 * C1) + (A2 * C2) with A1, A2 or C1, C2 being the same or
one. Make sure the type is not saturating and has the signedness of
the stripped operands, as fold_plusminus_mult_expr will re-associate.
@@ -9652,28 +9632,6 @@ fold_binary_loc (location_t loc,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)));
- if (! FLOAT_TYPE_P (type))
- {
- /* Fold (A & ~B) - (A & B) into (A ^ B) - B, where B is
- any power of 2 minus 1. */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == BIT_AND_EXPR
- && operand_equal_p (TREE_OPERAND (arg0, 0),
- TREE_OPERAND (arg1, 0), 0))
- {
- tree mask0 = TREE_OPERAND (arg0, 1);
- tree mask1 = TREE_OPERAND (arg1, 1);
- tree tem = fold_build1_loc (loc, BIT_NOT_EXPR, type, mask0);
-
- if (operand_equal_p (tem, mask1, 0))
- {
- tem = fold_build2_loc (loc, BIT_XOR_EXPR, type,
- TREE_OPERAND (arg0, 0), mask1);
- return fold_build2_loc (loc, MINUS_EXPR, type, tem, mask1);
- }
- }
- }
-
/* Fold __complex__ ( x, 0 ) - __complex__ ( 0, y ) to
__complex__ ( x, -y ). This is not the same for SNaNs or if
signed zeros are involved. */
@@ -9763,20 +9721,6 @@ fold_binary_loc (location_t loc,
goto associate;
case MULT_EXPR:
- /* (-A) * (-B) -> A * B */
- if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
- return fold_build2_loc (loc, MULT_EXPR, type,
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg0, 0)),
- fold_convert_loc (loc, type,
- negate_expr (arg1)));
- if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
- return fold_build2_loc (loc, MULT_EXPR, type,
- fold_convert_loc (loc, type,
- negate_expr (arg0)),
- fold_convert_loc (loc, type,
- TREE_OPERAND (arg1, 0)));
-
if (! FLOAT_TYPE_P (type))
{
/* Transform x * -C into -x * C if x is easily negatable. */
@@ -9790,16 +9734,6 @@ fold_binary_loc (location_t loc,
negate_expr (arg0)),
tem);
- /* (a * (1 << b)) is (a << b) */
- if (TREE_CODE (arg1) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg1, 0)))
- return fold_build2_loc (loc, LSHIFT_EXPR, type, op0,
- TREE_OPERAND (arg1, 1));
- if (TREE_CODE (arg0) == LSHIFT_EXPR
- && integer_onep (TREE_OPERAND (arg0, 0)))
- return fold_build2_loc (loc, LSHIFT_EXPR, type, op1,
- TREE_OPERAND (arg0, 1));
-
/* (A + A) * C -> A * 2 * C */
if (TREE_CODE (arg0) == PLUS_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
@@ -9842,21 +9776,6 @@ fold_binary_loc (location_t loc,
}
else
{
- /* Convert (C1/X)*C2 into (C1*C2)/X. This transformation may change
- the result for floating point types due to rounding so it is applied
- only if -fassociative-math was specify. */
- if (flag_associative_math
- && TREE_CODE (arg0) == RDIV_EXPR
- && TREE_CODE (arg1) == REAL_CST
- && TREE_CODE (TREE_OPERAND (arg0, 0)) == REAL_CST)
- {
- tree tem = const_binop (MULT_EXPR, TREE_OPERAND (arg0, 0),
- arg1);
- if (tem)
- return fold_build2_loc (loc, RDIV_EXPR, type, tem,
- TREE_OPERAND (arg0, 1));
- }
-
/* Strip sign operations from X in X*X, i.e. -Y*-Y -> Y*Y. */
if (operand_equal_p (arg0, arg1, 0))
{
@@ -9973,28 +9892,6 @@ fold_binary_loc (location_t loc,
arg1);
}
- /* (X & ~Y) | (~X & Y) is X ^ Y */
- if (TREE_CODE (arg0) == BIT_AND_EXPR
- && TREE_CODE (arg1) == BIT_AND_EXPR)
- {
- tree a0, a1, l0, l1, n0, n1;
-
- a0 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 0));
- a1 = fold_convert_loc (loc, type, TREE_OPERAND (arg1, 1));
-
- l0 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- l1 = fold_convert_loc (loc, type, TREE_OPERAND (arg0, 1));
-
- n0 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l0);
- n1 = fold_build1_loc (loc, BIT_NOT_EXPR, type, l1);
-
- if ((operand_equal_p (n0, a0, 0)
- && operand_equal_p (n1, a1, 0))
- || (operand_equal_p (n0, a1, 0)
- && operand_equal_p (n1, a0, 0)))
- return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
- }
-
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
@@ -10013,22 +9910,6 @@ fold_binary_loc (location_t loc,
goto bit_rotate;
case BIT_AND_EXPR:
- /* ~X & X, (X == 0) & X, and !X & X are always zero. */
- if ((TREE_CODE (arg0) == BIT_NOT_EXPR
- || TREE_CODE (arg0) == TRUTH_NOT_EXPR
- || (TREE_CODE (arg0) == EQ_EXPR
- && integer_zerop (TREE_OPERAND (arg0, 1))))
- && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
- return omit_one_operand_loc (loc, type, integer_zero_node, arg1);
-
- /* X & ~X , X & (X == 0), and X & !X are always zero. */
- if ((TREE_CODE (arg1) == BIT_NOT_EXPR
- || TREE_CODE (arg1) == TRUTH_NOT_EXPR
- || (TREE_CODE (arg1) == EQ_EXPR
- && integer_zerop (TREE_OPERAND (arg1, 1))))
- && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
- return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
-
/* Fold (X ^ 1) & 1 as (X & 1) == 0. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& INTEGRAL_TYPE_P (type)
diff --git a/gcc/match.pd b/gcc/match.pd
index b87c436..7210dfad 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -316,6 +316,47 @@ along with GCC; see the file COPYING3. If not see
(coss (op @0))
(coss @0))))
+/* Fold X + (X / CST) * -CST to X % CST. */
+(simplify
+ (plus (convert1? @0) (convert2? (mult (trunc_div @0 INTEGER_CST@1) INTEGER_CST@2)))
+ (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ && wi::add (@1, @2) == 0)
+ (trunc_mod (convert @0) (convert @1))))
+
+/* Fold (A & ~B) - (A & B) into (A ^ B) - B. */
+(simplify
+ (minus (bit_and:s @0 (bit_not @1)) (bit_and:s @0 @2))
+ (if (! FLOAT_TYPE_P (type)
+ && wi::eq_p (@1, @2))
+ (minus (bit_xor @0 @1) @1)))
+
+/* Fold (a * (1 << b)) into (a << b) */
+(simplify
+ (mult:c (convert1? @0) (convert2? (lshift integer_onep@1 @2)))
+ (if (! FLOAT_TYPE_P (type))
+ (lshift (convert @0) (convert @2))))
+
+/* Fold (C1/X)*C2 into (C1*C2)/X. */
+(simplify
+ (mult (rdiv REAL_CST@0 @1) REAL_CST@2)
+ (with
+ { tree tem = const_binop (MULT_EXPR, type, @0, @2); }
+ (if (tem && FLOAT_TYPE_P (type)
+ && flag_associative_math)
+ (rdiv (mult @0 @2) @1))))
+
+/* Simplify (X & ~Y) | (~X & Y) is X ^ Y. */
+(simplify
+ (bit_ior (bit_and:s @0 (bit_not @1)) (bit_and:s (bit_not @2) @3))
+ (if (wi::eq_p (@0, @2)
+ && wi::eq_p (@1, @3))
+ (bit_xor @0 @3)))
+
+/* Simplify ~X & X as zero. */
+(simplify
+ (bit_and:c (convert? @0) (convert? (bit_not @0)))
+ (convert { build_zero_cst (TREE_TYPE (@0)); }))
+
/* X % Y is smaller than Y. */
(for cmp (lt ge)
(simplify
@@ -549,6 +590,13 @@ along with GCC; see the file COPYING3. If not see
(if (!FIXED_POINT_TYPE_P (type))
(plus @0 (negate @1))))
+/* (-A) * (-B) -> A * B */
+(simplify
+ (mult:c (convert? (negate @0)) (convert? (negate @1)))
+ (if ((GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@0)))
+ || (GENERIC && type == TREE_TYPE (@0)))
+ (mult (convert @0) (convert @1))))
+
/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
when profitable.
For bitwise binary operations apply operand conversions to the