diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e0a2f3c0cc7ff154b7aae82e4f63235300bbb966..d3d6fff62e92c385e27ba37223347be00f5a277d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> + Alan Hayward <alan.hayward@arm.com> + David Sherwood <david.sherwood@arm.com> + + * match.pd: Handle bit operations involving three constants + and try to fold one pair. + 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> * tree-vect-loop-manip.c: Include gimple-fold.h. diff --git a/gcc/match.pd b/gcc/match.pd index 87012a243191e23e719a0e2766447c83d7adba91..06af2a72213316b8fe31d7a1ea8c0d658ef96e84 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1111,7 +1111,24 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for bitop (bit_and bit_ior bit_xor) (simplify (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2) - (bitop @0 (bitop @1 @2)))) + (if (!CONSTANT_CLASS_P (@0)) + /* This is the canonical form regardless of whether (bitop @1 @2) can be + folded to a constant. */ + (bitop @0 (bitop @1 @2)) + /* In this case we have three constants and (bitop @0 @1) doesn't fold + to a constant. This can happen if @0 or @1 is a POLY_INT_CST and if + the values involved are such that the operation can't be decided at + compile time. Try folding one of @0 or @1 with @2 to see whether + that combination can be decided at compile time. + + Keep the existing form if both folds fail, to avoid endless + oscillation. */ + (with { tree cst1 = const_binop (bitop, type, @0, @2); } + (if (cst1) + (bitop @1 { cst1; }) + (with { tree cst2 = const_binop (bitop, type, @1, @2); } + (if (cst2) + (bitop @0 { cst2; })))))))) /* Try simple folding for X op !X, and X op X with the help of the truth_valued_p and logical_inverted_value predicates. */