diff mbox

Move X==15-X to match.pd

Message ID alpine.DEB.2.02.1705180813100.19066@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse May 18, 2017, 6:24 a.m. UTC
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.glisse@inria.fr>

 	* fold-const.c (fold_binary_loc): Move transformation...
 	* match.pd (C - X CMP X): ... here.

Comments

Richard Biener May 18, 2017, 7:14 a.m. UTC | #1
On Thu, May 18, 2017 at 8:24 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> 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?

I think it's good to have a match.pd pattern given not all passes do
bit-tracking
and it can remove the need to iterate, say, FRE and CCP.  Maybe it can
even be usefully extended to arbitrary ops with using known-zero-bits
(just guessing here, simply moving it using wide-int ops rather than
fold for D & ~C works for me as well).

> Bootstrap+testsuite on powerpc64le-unknown-linux-gnu.

Ok.

Thanks,
Richard.

> 2017-05-18  Marc Glisse  <marc.glisse@inria.fr>
>
>         * fold-const.c (fold_binary_loc): Move transformation...
>         * match.pd (C - X CMP X): ... here.
>
> --
> Marc Glisse
diff mbox

Patch

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)
 */