The following patch adds more comparison patterns (with comments
on what is missing still).

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-09-02  Richard Biener  <rguent...@suse.de>

        * fold-const.h (negate_expr_p): Declare.
        * fold-const.c (negate_expr_p): Export.
        * match-comparison.pd: Implement more comparison patterns.

Index: gcc/match-comparison.pd
===================================================================
*** gcc/match-comparison.pd.orig        2014-09-02 11:10:06.855348847 +0200
--- gcc/match-comparison.pd     2014-09-02 13:30:52.392767381 +0200
***************
*** 1,3 ****
--- 1,62 ----
+ /* From fold_binary.  */
+ 
+ (simplify
+  (ne @0 integer_zerop@1)
+  (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE)
+   /* ???  In GENERIC the type of the comparison may be 'int'.  */
+   (convert @0)))
+ 
+ /* Distribute operations in equality compares.  */
+ (for op in eq ne
+  /* -exp op CST is exp op -CST.  */
+  (simplify
+   (op (negate @0) INTEGER_CST@1)
+   /* ??? fix fold-const to use negate_expr_p  */
+   (if (negate_expr_p (@1))
+    (op @0 (negate @1))))
+  /* X ^ C1 == C2 is X == (C1 ^ C2).  */
+  (simplify
+   (op (bit_xor @0 INTEGER_CST@1) INTEGER_CST@2)
+   (op @0 (bit_xor @1 @2))))
+ 
+ /* From fold_comparison, in the order of transforms in there.  */
+ 
+ /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1.  */
+ (for cmp in lt le eq ge gt ne
+  (for op in plus minus
+   (simplify
+    (cmp (op @0 INTEGER_CST@1) INTEGER_CST@2)
+    (if ((cmp == NE_EXPR || cmp == EQ_EXPR
+        || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+       && (@3 = int_const_binop (op == MINUS_EXPR ? PLUS_EXPR : MINUS_EXPR, 
@2, @1))
+       /* ???  fold_comparison here does, when @1 and @2 didn't have
+          TREE_OVERFLOW set, simplify the comparison to true/false
+          by using a staturated add.  */
+       && !TREE_OVERFLOW (@3))
+     (cmp @0 @3)))))
+ 
+ /* Transform comparisons of the form X - Y CMP 0 to X CMP Y.  */
+ /* ??? The transformation is valid for the other operators if overflow
+    is undefined for the type, but performing it here badly interacts
+    with the transformation in fold_cond_expr_with_comparison which
+    attempts to synthetize ABS_EXPR.  */
+ (for cmp in eq ne
+  (simplify
+   (cmp (minus @0 @1) integer_zerop)
+   (cmp @0 @1)))
+ 
+ /* For comparisons of pointers we can decompose it to a compile time
+    comparison of the base objects and the offsets into the object.
+    This requires at least one operand being an ADDR_EXPR or a
+    POINTER_PLUS_EXPR to do more than the operand_equal_p test below.  */
+ #if 0
+ (for cmp in lt le eq ge gt ne
+  (for op in addr pointer_plus
+   (simplify
+    (cmp:c (op@0 @1 @2) @3)
+    (if (simplify_addr_comparison (@0, @3, @@))))))
+ #endif
+ 
  /* Simplify X * C1 CMP 0 to X CMP 0 if C1 is not zero.  */
  (for op in lt le eq ne ge gt
    (simplify
***************
*** 13,15 ****
--- 72,141 ----
       (if (tree_int_cst_sgn (@1) < 0)
        (op @2 @0)))))
  
+ #if 0
+ /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
+    constant, we can simplify it.  */
+ (for op in min max
+  (for cmp in eq gt
+   (cmp (op @0 INTEGER_CST@1) INTEGER_CST@2)
+   (if (op == MAX_EXPR && tree_int_cst_compare (@1, @2) == 0)
+    (le @0 @2))
+   (if (
+       )
+    /* ??? optimize_minmax_comparison handles ne, lt and le by
+       recursing with an inverted comparison and then inverting
+       the result.  Or combining equality and gt with truth_or.   */)
+ #endif
+ 
+ /* Simplify comparison of something with itself.  For IEEE
+    floating-point, we can only do some of these simplifications.  */
+ (for cmp in ge le
+  (simplify
+   (cmp @0 @0)
+   (eq @0 @0)))
+ (simplify
+  (eq @0 @0)
+  (if (! FLOAT_TYPE_P (TREE_TYPE (@0))
+       || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0))))
+   { constant_boolean_node (true, type); }))
+ (for cmp in ne gt lt
+  (simplify
+   (cmp @0 @0)
+   (if (cmp != NE_EXPR
+        || ! FLOAT_TYPE_P (TREE_TYPE (@0))
+        || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (@0))))
+    { constant_boolean_node (false, type); })))
+ 
+ /* Need to split up the cases in twoval_comparison_p.  */
+ 
+ #if 0
+ /* We can fold X/C1 op C2 where C1 and C2 are integer constants
+    into a single range test.  */
+ (for cmp in lt le eq ge gt ne
+  (for div in trunc_div exact_div
+   (simplify
+    (cmp (div @0 INTEGER_CST@1) INTEGER_CST)
+    (if (!integer_zerop (@1))
+    /* ???  Need to think about what fold_div_compare does.  IMHO
+       we can unconditionally build a
+       (unsigned)@0 +- CST <= CST'
+       range check.  */
+   ))))
+ #endif
+ 
+ /* Fold ~X op ~Y as Y op X.  */
+ (for cmp in lt le eq ge gt ne
+  (simplify
+   (cmp (bit_not @0) (bit_not @1))
+   (cmp @1 @0)))
+ 
+ /* Fold ~X op C as X op' ~C, where op' is the swapped comparison.  */
+ (for cmp in lt le eq ge gt ne
+  (simplify
+   (cmp (bit_not @0) @1)
+   /* ???  (for cst in INTEGER_CST VECTOR_CST) is not supported yet.  */
+   (if ((TREE_CODE (@1) == INTEGER_CST || TREE_CODE (@1) == VECTOR_CST))
+   /* fold_comparison uses swapped 'cmp' to canonicalize the result
+      (constants second operand), swapping 'cmp' isn't available so we
+      cheat here and leave canonicalization to re-simplifying.  */
+    (cmp (bit_not @1) @0))))
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig       2014-09-02 11:10:06.855348847 +0200
--- gcc/fold-const.c    2014-09-02 13:24:21.284794309 +0200
*************** enum comparison_code {
*** 98,104 ****
  };
  
  static bool negate_mathfn_p (enum built_in_function);
- static bool negate_expr_p (tree);
  static tree negate_expr (tree);
  static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
  static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
--- 98,103 ----
*************** may_negate_without_overflow_p (const_tre
*** 373,379 ****
  /* Determine whether an expression T can be cheaply negated using
     the function negate_expr without introducing undefined overflow.  */
  
! static bool
  negate_expr_p (tree t)
  {
    tree type;
--- 372,378 ----
  /* Determine whether an expression T can be cheaply negated using
     the function negate_expr without introducing undefined overflow.  */
  
! bool
  negate_expr_p (tree t)
  {
    tree type;
Index: gcc/fold-const.h
===================================================================
*** gcc/fold-const.h.orig       2014-09-02 11:10:06.855348847 +0200
--- gcc/fold-const.h    2014-09-02 13:24:21.285794309 +0200
*************** extern tree make_range_step (location_t,
*** 167,171 ****
--- 167,172 ----
  extern tree build_range_check (location_t, tree, tree, int, tree, tree);
  extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
                          tree, tree);
+ extern bool negate_expr_p (tree);
  
  #endif // GCC_FOLD_CONST_H

Reply via email to