fold-const.c (distribute_bit_expr): Remove.

2015-07-10  Richard Biener  <rguenther@suse.de>

	* fold-const.c (distribute_bit_expr): Remove.
	(fold_binary_loc): Move simplifying (A & C1) + (B & C2)
	to (A & C1) | (B & C2), distributing (A & B) | (A & C)
	to A & (B | C) and simplifying A << C1 << C2 to ...
	* match.pd: ... patterns here.

From-SVN: r225670
This commit is contained in:
Richard Biener 2015-07-10 12:31:05 +00:00 committed by Richard Biener
parent 53021678c5
commit 14ea9f9283
3 changed files with 51 additions and 114 deletions

View File

@ -1,3 +1,11 @@
2015-07-10 Richard Biener <rguenther@suse.de>
* fold-const.c (distribute_bit_expr): Remove.
(fold_binary_loc): Move simplifying (A & C1) + (B & C2)
to (A & C1) | (B & C2), distributing (A & B) | (A & C)
to A & (B | C) and simplifying A << C1 << C2 to ...
* match.pd: ... patterns here.
2015-07-10 Jiong Wang <jiong.wang@arm.com>
* config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Mark mem

View File

@ -118,7 +118,6 @@ static enum tree_code compcode_to_comparison (enum comparison_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
static tree eval_subst (location_t, tree, tree, tree, tree, tree);
static tree distribute_bit_expr (location_t, enum tree_code, tree, tree, tree);
static tree make_bit_field_ref (location_t, tree, tree,
HOST_WIDE_INT, HOST_WIDE_INT, int);
static tree optimize_bit_field_compare (location_t, enum tree_code,
@ -3550,62 +3549,6 @@ invert_truthvalue_loc (location_t loc, tree arg)
type, arg);
}
/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
operands are another bit-wise operation with a common input. If so,
distribute the bit operations to save an operation and possibly two if
constants are involved. For example, convert
(A | B) & (A | C) into A | (B & C)
Further simplification will occur if B and C are constants.
If this optimization cannot be done, 0 will be returned. */
static tree
distribute_bit_expr (location_t loc, enum tree_code code, tree type,
tree arg0, tree arg1)
{
tree common;
tree left, right;
if (TREE_CODE (arg0) != TREE_CODE (arg1)
|| TREE_CODE (arg0) == code
|| (TREE_CODE (arg0) != BIT_AND_EXPR
&& TREE_CODE (arg0) != BIT_IOR_EXPR))
return 0;
if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 0), 0))
{
common = TREE_OPERAND (arg0, 0);
left = TREE_OPERAND (arg0, 1);
right = TREE_OPERAND (arg1, 1);
}
else if (operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1, 1), 0))
{
common = TREE_OPERAND (arg0, 0);
left = TREE_OPERAND (arg0, 1);
right = TREE_OPERAND (arg1, 0);
}
else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0), 0))
{
common = TREE_OPERAND (arg0, 1);
left = TREE_OPERAND (arg0, 0);
right = TREE_OPERAND (arg1, 1);
}
else if (operand_equal_p (TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 1), 0))
{
common = TREE_OPERAND (arg0, 1);
left = TREE_OPERAND (arg0, 0);
right = TREE_OPERAND (arg1, 0);
}
else
return 0;
common = fold_convert_loc (loc, type, common);
left = fold_convert_loc (loc, type, left);
right = fold_convert_loc (loc, type, right);
return fold_build2_loc (loc, TREE_CODE (arg0), type, common,
fold_build2_loc (loc, code, type, left, right));
}
/* Knowing that ARG0 and ARG1 are both RDIV_EXPRs, simplify a binary operation
with code CODE. This optimization is unsafe. */
static tree
@ -9575,21 +9518,6 @@ fold_binary_loc (location_t loc,
if (! FLOAT_TYPE_P (type))
{
/* If we are adding two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
we should treat this as a BIT_IOR_EXPR since this may produce more
simplifications. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
&& wi::bit_and (TREE_OPERAND (arg0, 1),
TREE_OPERAND (arg1, 1)) == 0)
{
code = BIT_IOR_EXPR;
goto bit_ior;
}
/* Reassociate (plus (plus (mult) (foo)) (mult)) as
(plus (plus (mult) (mult)) (foo)) so that we can
take advantage of the factoring cases below. */
@ -10423,7 +10351,6 @@ fold_binary_loc (location_t loc,
goto associate;
case BIT_IOR_EXPR:
bit_ior:
/* Canonicalize (X & C1) | C2. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
@ -10494,10 +10421,6 @@ fold_binary_loc (location_t loc,
return fold_build2_loc (loc, BIT_XOR_EXPR, type, l0, n1);
}
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
/* See if this can be simplified into a rotate first. If that
is unsuccessful continue in the association code. */
goto bit_rotate;
@ -10760,9 +10683,6 @@ fold_binary_loc (location_t loc,
}
}
t1 = distribute_bit_expr (loc, code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
/* Simplify ((int)c & 0377) into (int)c, if c is unsigned char. */
if (TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg0) == NOP_EXPR
&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
@ -11111,32 +11031,6 @@ fold_binary_loc (location_t loc,
prec = element_precision (type);
/* Turn (a OP c1) OP c2 into a OP (c1+c2). */
if (TREE_CODE (op0) == code && tree_fits_uhwi_p (arg1)
&& tree_to_uhwi (arg1) < prec
&& tree_fits_uhwi_p (TREE_OPERAND (arg0, 1))
&& tree_to_uhwi (TREE_OPERAND (arg0, 1)) < prec)
{
unsigned int low = (tree_to_uhwi (TREE_OPERAND (arg0, 1))
+ tree_to_uhwi (arg1));
/* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
being well defined. */
if (low >= prec)
{
if (code == LROTATE_EXPR || code == RROTATE_EXPR)
low = low % prec;
else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
return omit_one_operand_loc (loc, type, build_zero_cst (type),
TREE_OPERAND (arg0, 0));
else
low = prec - 1;
}
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
build_int_cst (TREE_TYPE (arg1), low));
}
/* Transform (x >> c) << c into x & (-1<<c), or transform (x << c) >> c
into x & ((unsigned)-1 >> c) for unsigned types. */
if (((code == LSHIFT_EXPR && TREE_CODE (arg0) == RSHIFT_EXPR)

View File

@ -419,17 +419,18 @@ along with GCC; see the file COPYING3. If not see
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(bit_not (rop (convert @0) (convert @1))))))
/* If we are XORing two BIT_AND_EXPR's, both of which are and'ing
/* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing
with a constant, and the two constants have no bits in common,
we should treat this as a BIT_IOR_EXPR since this may produce more
simplifications. */
(simplify
(bit_xor (convert1? (bit_and@4 @0 INTEGER_CST@1))
(convert2? (bit_and@5 @2 INTEGER_CST@3)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@2))
&& wi::bit_and (@1, @3) == 0)
(bit_ior (convert @4) (convert @5))))
(for op (bit_xor plus)
(simplify
(op (convert1? (bit_and@4 @0 INTEGER_CST@1))
(convert2? (bit_and@5 @2 INTEGER_CST@3)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@0))
&& tree_nop_conversion_p (type, TREE_TYPE (@2))
&& wi::bit_and (@1, @3) == 0)
(bit_ior (convert @4) (convert @5)))))
/* (X | Y) ^ X -> Y & ~ X*/
(simplify
@ -455,6 +456,19 @@ along with GCC; see the file COPYING3. If not see
(bit_xor:c (bit_and:c @0 @1) @1)
(bit_and (bit_not @0) @1))
/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
operands are another bit-wise operation with a common input. If so,
distribute the bit operations to save an operation and possibly two if
constants are involved. For example, convert
(A | B) & (A | C) into A | (B & C)
Further simplification will occur if B and C are constants. */
(for op (bit_and bit_ior)
rop (bit_ior bit_and)
(simplify
(op (convert? (rop:c @0 @1)) (convert? (rop @0 @2)))
(if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
(rop (convert @0) (op (convert @1) (convert @2))))))
(simplify
(abs (abs@1 @0))
@ -880,6 +894,27 @@ along with GCC; see the file COPYING3. If not see
build_int_cst (TREE_TYPE (@1),
element_precision (type)), @1); }))
/* Turn (a OP c1) OP c2 into a OP (c1+c2). */
(for op (lrotate rrotate rshift lshift)
(simplify
(op (op @0 INTEGER_CST@1) INTEGER_CST@2)
(with { unsigned int prec = element_precision (type); }
(if (wi::ge_p (@1, 0, TYPE_SIGN (TREE_TYPE (@1)))
&& wi::lt_p (@1, prec, TYPE_SIGN (TREE_TYPE (@1)))
&& wi::ge_p (@2, 0, TYPE_SIGN (TREE_TYPE (@2)))
&& wi::lt_p (@2, prec, TYPE_SIGN (TREE_TYPE (@2))))
(with { unsigned int low = wi::add (@1, @2).to_uhwi (); }
/* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
being well defined. */
(if (low >= prec)
(if (op == LROTATE_EXPR || op == RROTATE_EXPR)
(op @0 { build_int_cst (TREE_TYPE (@1), low % prec); }))
(if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR)
{ build_zero_cst (type); })
(op @0 { build_int_cst (TREE_TYPE (@1), prec - 1); }))
(op @0 { build_int_cst (TREE_TYPE (@1), low); }))))))
/* ((1 << A) & 1) != 0 -> A == 0
((1 << A) & 1) == 0 -> A != 0 */
(for cmp (ne eq)