Hello,just moving one simple transformation to match.pd. It is actually slightly more general, because there is no point restricting to NOP conversions when only the lowest bit matters.
By the way, I was thinking of removing from fold-const.c the transformation "If we have (A & C) == D where D & ~C != 0, convert this into 0." because it is already handled by CCP. Would that be ok or does it still need an equivalent match.pd version?
Bootstrap+testsuite on powerpc64le-unknown-linux-gnu. 2017-05-18 Marc Glisse <marc.gli...@inria.fr> * fold-const.c (fold_binary_loc): Move transformation... * match.pd (C - X CMP X): ... here. -- Marc Glisse
Index: fold-const.c =================================================================== --- fold-const.c (revision 248173) +++ fold-const.c (working copy) @@ -10525,44 +10525,20 @@ fold_binary_loc (location_t loc, && (INTEGRAL_TYPE_P (TREE_TYPE (arg1)) || POINTER_TYPE_P (TREE_TYPE (arg1)))) { tree val = TREE_OPERAND (arg1, 1); val = fold_build2_loc (loc, code, type, val, build_int_cst (TREE_TYPE (val), 0)); return omit_two_operands_loc (loc, type, val, TREE_OPERAND (arg1, 0), arg0); } - /* Transform comparisons of the form C - X CMP X if C % 2 == 1. */ - if (TREE_CODE (arg0) == MINUS_EXPR - && TREE_CODE (TREE_OPERAND (arg0, 0)) == INTEGER_CST - && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg0, - 1)), - arg1, 0) - && wi::extract_uhwi (TREE_OPERAND (arg0, 0), 0, 1) == 1) - return omit_two_operands_loc (loc, type, - code == NE_EXPR - ? boolean_true_node : boolean_false_node, - TREE_OPERAND (arg0, 1), arg1); - - /* Transform comparisons of the form X CMP C - X if C % 2 == 1. */ - if (TREE_CODE (arg1) == MINUS_EXPR - && TREE_CODE (TREE_OPERAND (arg1, 0)) == INTEGER_CST - && operand_equal_p (tree_strip_nop_conversions (TREE_OPERAND (arg1, - 1)), - arg0, 0) - && wi::extract_uhwi (TREE_OPERAND (arg1, 0), 0, 1) == 1) - return omit_two_operands_loc (loc, type, - code == NE_EXPR - ? boolean_true_node : boolean_false_node, - TREE_OPERAND (arg1, 1), arg0); - /* If this is an EQ or NE comparison with zero and ARG0 is (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require two operations, but the latter can be done in one less insn on machines that have only two-operand insns or on which a constant cannot be the first operand. */ if (TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)) { tree arg00 = TREE_OPERAND (arg0, 0); tree arg01 = TREE_OPERAND (arg0, 1); Index: match.pd =================================================================== --- match.pd (revision 248173) +++ match.pd (working copy) @@ -1083,20 +1083,27 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (op @1 @0)))) /* For equality and subtraction, this is also true with wrapping overflow. */ (for op (eq ne minus) (simplify (op (minus @2 @0) (minus @2 @1)) (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)) || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))) (op @1 @0)))) +/* X == C - X can never be true if C is odd. */ +(for cmp (eq ne) + (simplify + (cmp:c (convert? @0) (convert1? (minus INTEGER_CST@1 (convert2? @0)))) + (if (TREE_INT_CST_LOW (@1) & 1) + { constant_boolean_node (cmp == NE_EXPR, type); }))) + /* ((X inner_op C0) outer_op C1) With X being a tree where value_range has reasoned certain bits to always be zero throughout its computed value range, inner_op = {|,^}, outer_op = {|,^} and inner_op != outer_op where zero_mask has 1's for all bits that are sure to be 0 in and 0's otherwise. if (inner_op == '^') C0 &= ~C1; if ((C0 & ~zero_mask) == 0) then emit (X outer_op (C0 outer_op C1) if ((C1 & ~zero_mask) == 0) then emit (X inner_op (C0 outer_op C1) */