* [PATCH][14/n] Remove GENERIC stmt combining from SCCVN
@ 2015-07-09 12:35 Richard Biener
2015-07-10 12:32 ` Richard Biener
0 siblings, 1 reply; 2+ messages in thread
From: Richard Biener @ 2015-07-09 12:35 UTC (permalink / raw)
To: gcc-patches
This moves more patterns that show up during bootstrap.
Bootstrap and regtest running on x86_64-unknown-linux-gnu.
Richard.
2015-07-09 Richard Biener <rguenther@suse.de>
* fold-const.c (distribute_bit_expr): Remove.
(fold_plusminus_mult_expr): Likewise.
(fold_binary_loc): Move factoring out common multiples
from (A * B) +- (C * D), 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.
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c (revision 225609)
--- gcc/fold-const.c (working copy)
*************** static enum tree_code compcode_to_compar
*** 117,123 ****
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,
--- 117,122 ----
*************** invert_truthvalue_loc (location_t loc, t
*** 3549,3610 ****
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
--- 3548,3553 ----
*************** fold_to_nonsharp_ineq_using_bound (locat
*** 6937,7064 ****
return fold_build2_loc (loc, GE_EXPR, type, a, y);
}
- /* Fold a sum or difference of at least one multiplication.
- Returns the folded tree or NULL if no simplification could be made. */
-
- static tree
- fold_plusminus_mult_expr (location_t loc, enum tree_code code, tree type,
- tree arg0, tree arg1)
- {
- tree arg00, arg01, arg10, arg11;
- tree alt0 = NULL_TREE, alt1 = NULL_TREE, same;
-
- /* (A * C) +- (B * C) -> (A+-B) * C.
- (A * C) +- A -> A * (C+-1).
- We are most concerned about the case where C is a constant,
- but other combinations show up during loop reduction. Since
- it is not difficult, try all four possibilities. */
-
- if (TREE_CODE (arg0) == MULT_EXPR)
- {
- arg00 = TREE_OPERAND (arg0, 0);
- arg01 = TREE_OPERAND (arg0, 1);
- }
- else if (TREE_CODE (arg0) == INTEGER_CST)
- {
- arg00 = build_one_cst (type);
- arg01 = arg0;
- }
- else
- {
- /* We cannot generate constant 1 for fract. */
- if (ALL_FRACT_MODE_P (TYPE_MODE (type)))
- return NULL_TREE;
- arg00 = arg0;
- arg01 = build_one_cst (type);
- }
- if (TREE_CODE (arg1) == MULT_EXPR)
- {
- arg10 = TREE_OPERAND (arg1, 0);
- arg11 = TREE_OPERAND (arg1, 1);
- }
- else if (TREE_CODE (arg1) == INTEGER_CST)
- {
- arg10 = build_one_cst (type);
- /* As we canonicalize A - 2 to A + -2 get rid of that sign for
- the purpose of this canonicalization. */
- if (wi::neg_p (arg1, TYPE_SIGN (TREE_TYPE (arg1)))
- && negate_expr_p (arg1)
- && code == PLUS_EXPR)
- {
- arg11 = negate_expr (arg1);
- code = MINUS_EXPR;
- }
- else
- arg11 = arg1;
- }
- else
- {
- /* We cannot generate constant 1 for fract. */
- if (ALL_FRACT_MODE_P (TYPE_MODE (type)))
- return NULL_TREE;
- arg10 = arg1;
- arg11 = build_one_cst (type);
- }
- same = NULL_TREE;
-
- if (operand_equal_p (arg01, arg11, 0))
- same = arg01, alt0 = arg00, alt1 = arg10;
- else if (operand_equal_p (arg00, arg10, 0))
- same = arg00, alt0 = arg01, alt1 = arg11;
- else if (operand_equal_p (arg00, arg11, 0))
- same = arg00, alt0 = arg01, alt1 = arg10;
- else if (operand_equal_p (arg01, arg10, 0))
- same = arg01, alt0 = arg00, alt1 = arg11;
-
- /* No identical multiplicands; see if we can find a common
- power-of-two factor in non-power-of-two multiplies. This
- can help in multi-dimensional array access. */
- else if (tree_fits_shwi_p (arg01)
- && tree_fits_shwi_p (arg11))
- {
- HOST_WIDE_INT int01, int11, tmp;
- bool swap = false;
- tree maybe_same;
- int01 = tree_to_shwi (arg01);
- int11 = tree_to_shwi (arg11);
-
- /* Move min of absolute values to int11. */
- if (absu_hwi (int01) < absu_hwi (int11))
- {
- tmp = int01, int01 = int11, int11 = tmp;
- alt0 = arg00, arg00 = arg10, arg10 = alt0;
- maybe_same = arg01;
- swap = true;
- }
- else
- maybe_same = arg11;
-
- if (exact_log2 (absu_hwi (int11)) > 0 && int01 % int11 == 0
- /* The remainder should not be a constant, otherwise we
- end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
- increased the number of multiplications necessary. */
- && TREE_CODE (arg10) != INTEGER_CST)
- {
- alt0 = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (arg00), arg00,
- build_int_cst (TREE_TYPE (arg00),
- int01 / int11));
- alt1 = arg10;
- same = maybe_same;
- if (swap)
- maybe_same = alt0, alt0 = alt1, alt1 = maybe_same;
- }
- }
-
- if (same)
- return fold_build2_loc (loc, MULT_EXPR, type,
- fold_build2_loc (loc, code, type,
- fold_convert_loc (loc, type, alt0),
- fold_convert_loc (loc, type, alt1)),
- fold_convert_loc (loc, type, same));
-
- return NULL_TREE;
- }
-
/* Subroutine of native_encode_expr. Encode the INTEGER_CST
specified by EXPR into the buffer PTR of length LEN bytes.
Return the number of bytes placed in the buffer, or zero
--- 6880,6885 ----
*************** fold_binary_loc (location_t loc,
*** 9556,9594 ****
}
}
- /* 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.
- ??? The latter condition should use TYPE_OVERFLOW_* flags instead. */
- if ((TREE_CODE (arg0) == MULT_EXPR
- || TREE_CODE (arg1) == MULT_EXPR)
- && !TYPE_SATURATING (type)
- && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg0))
- && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg1))
- && (!FLOAT_TYPE_P (type) || flag_associative_math))
- {
- tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
- }
-
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. */
--- 9377,9384 ----
*************** fold_binary_loc (location_t loc,
*** 10120,10141 ****
&& (tem = distribute_real_division (loc, code, type, arg0, arg1)))
return tem;
- /* 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.
- ??? The latter condition should use TYPE_OVERFLOW_* flags instead. */
- if ((TREE_CODE (arg0) == MULT_EXPR
- || TREE_CODE (arg1) == MULT_EXPR)
- && !TYPE_SATURATING (type)
- && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg0))
- && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (TREE_TYPE (arg1))
- && (!FLOAT_TYPE_P (type) || flag_associative_math))
- {
- tree tem = fold_plusminus_mult_expr (loc, code, type, arg0, arg1);
- if (tem)
- return tem;
- }
-
goto associate;
case MULT_EXPR:
--- 9910,9915 ----
*************** fold_binary_loc (location_t loc,
*** 10422,10428 ****
goto associate;
case BIT_IOR_EXPR:
- bit_ior:
/* Canonicalize (X & C1) | C2. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
--- 10196,10201 ----
*************** fold_binary_loc (location_t loc,
*** 10493,10502 ****
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;
--- 10266,10271 ----
*************** fold_binary_loc (location_t loc,
*** 10759,10767 ****
}
}
- 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))))
--- 10528,10533 ----
*************** fold_binary_loc (location_t loc,
*** 11110,11141 ****
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)
--- 10876,10881 ----
Index: gcc/match.pd
===================================================================
*** gcc/match.pd (revision 225610)
--- gcc/match.pd (working copy)
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 419,435 ****
&& 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
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))))
/* (X | Y) ^ X -> Y & ~ X*/
(simplify
--- 419,436 ----
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(bit_not (rop (convert @0) (convert @1))))))
! /* 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. */
! (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
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 455,460 ****
--- 456,474 ----
(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))
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 821,826 ****
--- 835,880 ----
&& tree_int_cst_sign_bit (@1) == 0))
(convert @1))))))
+ /* From fold_plusminus_mult_expr. */
+ (if (! TYPE_SATURATING (type)
+ && (! FLOAT_TYPE_P (type) || flag_associative_math))
+ (for op (plus minus)
+ /* (A * B) +- (A * C) -> A * (B +- C) */
+ (simplify
+ (op (mult:cs @0 @1) (mult:s @0 @2))
+ (mult @0 (op @1 @2)))
+ /* (A * B) +- A -> A * (B +- 1) */
+ (simplify
+ (op (mult:cs @0 @1) @0)
+ (if (! ALL_FRACT_MODE_P (TYPE_MODE (type)))
+ (mult @0 (op @1 { build_one_cst (type); }))))
+ /* A +- (A * B) -> A * (1 +- B) */
+ (simplify
+ (op @0 (mult:cs @0 @1))
+ (if (! ALL_FRACT_MODE_P (TYPE_MODE (type)))
+ (mult @0 (op { build_one_cst (type); } @1))))
+ /* No identical multiplicands; see if we can find a common
+ power-of-two factor in non-power-of-two multiplies. This
+ can help in multi-dimensional array access.
+ Both operands should be multiplies, otherwise we
+ end up folding i * 4 + 2 to (i * 2 + 1) * 2 which has
+ increased the number of multiplications necessary. */
+ (simplify
+ (op (mult:s @0 INTEGER_CST@1) (mult:s @2 INTEGER_CST@3))
+ (if (tree_fits_shwi_p (@1)
+ && tree_fits_shwi_p (@3))
+ (with
+ {
+ HOST_WIDE_INT factor1 = tree_to_shwi (@1);
+ HOST_WIDE_INT factor3 = tree_to_shwi (@3);
+ }
+ (if (factor1 % factor3 == 0)
+ (mult (op (mult @0 { build_int_cst (type, factor1 / factor3); }) @2)
+ { build_int_cst (type, factor3); }))
+ (if (factor3 % factor1 == 0)
+ (mult (op (mult @2 { build_int_cst (type, factor3 / factor1); }) @0)
+ { build_int_cst (type, factor1); })))))))
+
/* Simplifications of MIN_EXPR and MAX_EXPR. */
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 880,885 ****
--- 934,960 ----
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)
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH][14/n] Remove GENERIC stmt combining from SCCVN
2015-07-09 12:35 [PATCH][14/n] Remove GENERIC stmt combining from SCCVN Richard Biener
@ 2015-07-10 12:32 ` Richard Biener
0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2015-07-10 12:32 UTC (permalink / raw)
To: gcc-patches
On Thu, 9 Jul 2015, Richard Biener wrote:
>
> This moves more patterns that show up during bootstrap.
>
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
Due to regressions caused I split off the fold_plusminus_mult_expr
part.
Bootstrapped and tested on x86_64-unknown-linux-gnu, committed.
Richard.
2015-07-09 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.
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c (revision 225657)
--- gcc/fold-const.c (working copy)
*************** static enum tree_code compcode_to_compar
*** 117,123 ****
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,
--- 117,122 ----
*************** invert_truthvalue_loc (location_t loc, t
*** 3549,3610 ****
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
--- 3548,3553 ----
*************** fold_binary_loc (location_t loc,
*** 9574,9594 ****
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. */
--- 9517,9522 ----
*************** fold_binary_loc (location_t loc,
*** 10422,10428 ****
goto associate;
case BIT_IOR_EXPR:
- bit_ior:
/* Canonicalize (X & C1) | C2. */
if (TREE_CODE (arg0) == BIT_AND_EXPR
&& TREE_CODE (arg1) == INTEGER_CST
--- 10350,10355 ----
*************** fold_binary_loc (location_t loc,
*** 10493,10502 ****
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;
--- 10420,10425 ----
*************** fold_binary_loc (location_t loc,
*** 10759,10767 ****
}
}
- 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))))
--- 10682,10687 ----
*************** fold_binary_loc (location_t loc,
*** 11110,11141 ****
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)
--- 11030,11035 ----
Index: gcc/match.pd
===================================================================
*** gcc/match.pd (revision 225657)
--- gcc/match.pd (working copy)
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 419,435 ****
&& 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
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))))
/* (X | Y) ^ X -> Y & ~ X*/
(simplify
--- 419,436 ----
&& tree_nop_conversion_p (type, TREE_TYPE (@1)))
(bit_not (rop (convert @0) (convert @1))))))
! /* 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. */
! (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
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 455,460 ****
--- 456,474 ----
(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))
*************** (define_operator_list CBRT BUILT_IN_CBRT
*** 880,885 ****
--- 894,920 ----
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)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-07-10 12:32 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-09 12:35 [PATCH][14/n] Remove GENERIC stmt combining from SCCVN Richard Biener
2015-07-10 12:32 ` Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).