Re: Move ABS detection from fold-const.c to match.pd

2015-06-29 Thread Richard Biener
On Sun, Jun 28, 2015 at 8:34 PM, Marc Glisse marc.gli...@inria.fr wrote:
 (this message looks like it was lost in my draft folder...)

 On Tue, 26 May 2015, Richard Biener wrote:

 +(match zerop integer_zerop)
 +(match zerop real_zerop)

 Would it also include fixed_zerop?


 Probably, yes. The main issue is that I know next to nothing about
 fixed-point types, so I am always unsure how to handle them (when I don't
 forget them completely). For instance, in the recently added -A CMP -B, we
 could probably replace

   (if (FLOAT_TYPE_P (TREE_TYPE (@0))
|| (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
 TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0

 with

   (if (FLOAT_TYPE_P (TREE_TYPE (@0))
|| TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))

Not sure if TYPE_OVERFLOW_UNDEFINED says sth sensible for fixed-point
types given that there is no overflow for them but they saturate.  As far as I
see the check would even ICE without guarding it with
ANY_INTEGRAL_TYPE_P.  So it would be

   || NON_SAT_FIXED_POINT_TYPE_P (TREE_TYPE (@0))

where I am not sure whether overflow is undefined for non-saturating fixed-point
types ...


 Note that with inlining implemented it would duplicate the pattern for
 each match variant thus in this case adding a tree.[ch] function zerop ()
 might be better.


 Ah... I actually thought we might end up moving things like integer_zerop
 from tree.c to match.pd, especially since predicates are not declared
 'static'... Ok, reverse gear.

Yeah, I don't think match.pd is a good fit for them.

 Note that inlining does not seem necessary to implement more advanced
 predicates like negated_value_for_comparison in the parent message.

Sure not necessary but one point of match-and-simplify was that
the pattern matching is fast because it uses a decision tree.  Once
you introduce predicates that are in functions with their own decision
tree you get back to testing all of them.

 +   (simplify
 +(cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))
 +(if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
 + @1)
 +(if (cmp == NE_EXPR || cmp == LTGT_EXPR)
 + (non_lvalue @2))
 +(if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */
 + TYPE_SIGN (type) == SIGNED
 + element_precision (type) = element_precision (TREE_TYPE
 (@0)))
 + (if (cmp == GE_EXPR || cmp == GT_EXPR
 + || (!flag_trapping_math  (cmp == UNGE_EXPR || cmp ==
 UNGT_EXPR)))
 +  (abs @2))
 + (if (cmp == LE_EXPR || cmp == LT_EXPR
 + || (!flag_trapping_math  (cmp == UNLE_EXPR || cmp ==
 UNLT_EXPR)))
 +  (negate (abs @2)
 +   /* Now with the branches swapped.  */
 +   (simplify
 +(cnd (cmp @0 zerop) (negate@1 (convert?@2 @0)) @2)

 not obvious from a quick look - but would you be able to remove the
 swapped branch
 vairant if (cnd:c (cmp @0 zerop) X Y) would work by swapping X and Y?


 Hmm. How do I test if I am currently in the original or commuted version of
 the simplification?

You can't.

 I could add a with block that defines truecmp as
 either cmp or invert_tree_comparison (cmp) and test that. Otherwise, I would
 need a test before each return as swapped versions don't return the same
 thing. It might make a slight difference on the handling of
 flag_trapping_math, but that handling already seems strange to me...

(cnd:c (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))

would get you

 (cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))

and

 (cnd (cmp @0 zerop) (negate@1 @2) (convert?@2 @0))

in the patterns it almost literally looked like what you did manually.

 The fold-const.c code doesn't seem to handle as many variants (esp.
 the swapping?),


 The fold-const.c function is called twice, once on regular operands, once
 with inverted comparison and swapped operands. I really don't think I am
 handling more cases (except maybe the silly a?a:0 is extended to unsigned).

Ok.

 so maybe you can add a testcase that exercises some of the above on
 GIMPLE?


 So mostly the VEC_COND_EXPR version? We don't seem to have that much
 COND_EXPR left in gimple.

Ah, true.  Yes, the vector variant then.

Thanks,
Richard.

 --
 Marc Glisse


Re: Move ABS detection from fold-const.c to match.pd

2015-06-28 Thread Marc Glisse

(this message looks like it was lost in my draft folder...)

On Tue, 26 May 2015, Richard Biener wrote:


+(match zerop integer_zerop)
+(match zerop real_zerop)

Would it also include fixed_zerop?


Probably, yes. The main issue is that I know next to nothing about 
fixed-point types, so I am always unsure how to handle them (when I don't 
forget them completely). For instance, in the recently added -A CMP -B, we 
could probably replace


  (if (FLOAT_TYPE_P (TREE_TYPE (@0))
   || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0

with

  (if (FLOAT_TYPE_P (TREE_TYPE (@0))
   || TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))


Note that with inlining implemented it would duplicate the pattern for 
each match variant thus in this case adding a tree.[ch] function zerop 
() might be better.


Ah... I actually thought we might end up moving things like integer_zerop 
from tree.c to match.pd, especially since predicates are not declared 
'static'... Ok, reverse gear.


Note that inlining does not seem necessary to implement more advanced 
predicates like negated_value_for_comparison in the parent message.



+   (simplify
+(cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))
+(if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ @1)
+(if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ (non_lvalue @2))
+(if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */
+ TYPE_SIGN (type) == SIGNED
+ element_precision (type) = element_precision (TREE_TYPE (@0)))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math  (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+  (abs @2))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math  (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+  (negate (abs @2)
+   /* Now with the branches swapped.  */
+   (simplify
+(cnd (cmp @0 zerop) (negate@1 (convert?@2 @0)) @2)

not obvious from a quick look - but would you be able to remove the
swapped branch
vairant if (cnd:c (cmp @0 zerop) X Y) would work by swapping X and Y?


Hmm. How do I test if I am currently in the original or commuted version 
of the simplification? I could add a with block that defines truecmp as 
either cmp or invert_tree_comparison (cmp) and test that. Otherwise, I 
would need a test before each return as swapped versions don't return 
the same thing. It might make a slight difference on the handling of 
flag_trapping_math, but that handling already seems strange to me...



The fold-const.c code doesn't seem to handle as many variants (esp.
the swapping?),


The fold-const.c function is called twice, once on regular operands, once 
with inverted comparison and swapped operands. I really don't think I am 
handling more cases (except maybe the silly a?a:0 is extended to 
unsigned).



so maybe you can add a testcase that exercises some of the above on GIMPLE?


So mostly the VEC_COND_EXPR version? We don't seem to have that much 
COND_EXPR left in gimple.


--
Marc Glisse


Re: Move ABS detection from fold-const.c to match.pd

2015-05-26 Thread Richard Biener
On Sun, May 24, 2015 at 3:17 PM, Marc Glisse marc.gli...@inria.fr wrote:

 I forgot to mention I optimistically tried to write something like this:

 (match
  (negated_value_for_comparison @0)
  (negate @0))
 (match
  (negated_value_for_comparison (negate @0))
  @0)
 (match
  (negated_value_for_comparison (minus @0 @1))
  (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type))
   (minus @1 @0))

 without success. There is already a comment for logical_inverted_value about
 related limitations in genmatch.

Yeah, Prathamesh was working on inlining - not sure if that ended up
in sth usable?

+(match zerop integer_zerop)
+(match zerop real_zerop)

Would it also include fixed_zerop?  Note that with inlining implemented it would
duplicate the pattern for each match variant thus in this case adding a
tree.[ch] function zerop () might be better.

+   (simplify
+(cnd (cmp @0 zerop) (convert?@2 @0) (negate@1 @2))
+(if (cmp == EQ_EXPR || cmp == UNEQ_EXPR)
+ @1)
+(if (cmp == NE_EXPR || cmp == LTGT_EXPR)
+ (non_lvalue @2))
+(if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED /* implicit */
+ TYPE_SIGN (type) == SIGNED
+ element_precision (type) = element_precision (TREE_TYPE (@0)))
+ (if (cmp == GE_EXPR || cmp == GT_EXPR
+ || (!flag_trapping_math  (cmp == UNGE_EXPR || cmp == UNGT_EXPR)))
+  (abs @2))
+ (if (cmp == LE_EXPR || cmp == LT_EXPR
+ || (!flag_trapping_math  (cmp == UNLE_EXPR || cmp == UNLT_EXPR)))
+  (negate (abs @2)
+   /* Now with the branches swapped.  */
+   (simplify
+(cnd (cmp @0 zerop) (negate@1 (convert?@2 @0)) @2)

not obvious from a quick look - but would you be able to remove the
swapped branch
vairant if (cnd:c (cmp @0 zerop) X Y) would work by swapping X and Y?

The fold-const.c code doesn't seem to handle as many variants (esp.
the swapping?),
so maybe you can add a testcase that exercises some of the above on GIMPLE?

Thanks,
Richard.


 --
 Marc Glisse


Re: Move ABS detection from fold-const.c to match.pd

2015-05-24 Thread Marc Glisse


I forgot to mention I optimistically tried to write something like this:

(match
 (negated_value_for_comparison @0)
 (negate @0))
(match
 (negated_value_for_comparison (negate @0))
 @0)
(match
 (negated_value_for_comparison (minus @0 @1))
 (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type))
  (minus @1 @0))

without success. There is already a comment for logical_inverted_value 
about related limitations in genmatch.


--
Marc Glisse


Move ABS detection from fold-const.c to match.pd

2015-05-24 Thread Marc Glisse

Hello,

I don't think this pattern is done in the branch. Here I am trying to 
match what is done in fold-const, but the idea is that we can later add an 
extra block where we replace (cmp (minus @2 @3) zerop) with (cmp @2 @3), 
maybe with some adjustments (convert? all over the place), to help with 
PR 64450 / PR 61734.


I didn't exactly match the code in fold-const.c, among other things 
because I didn't feel like calling operand_equal_for_comparison_p, and 
strip_nops can translate to quite heavy patterns. Except for a few 
irrelevant cases (where I simplify more), this seems to generate the same 
.original dumps in the cases I tried. But I am not claiming this is the 
best way to arrange that code, better ideas are welcome.


I don't understand the old code handling unsigned, but I couldn't find a 
case where the new code (doing nothing special for unsigned) generated a 
different .original dump. The last pattern had a strange mix of requiring 
integer_zerop and talking about signed zero and NaN, I didn't try to 
preserve that. The change to genmatch is for zerop, which doesn't try to 
valueize anything.


I had a few issues with the machinery. First, genmatch was generating 
a switch with duplicate cases (miraculously, replacing 'cond' with an 
iteration on 'cnd' worked around it). Second, (plus @0 (negate@0 @1)) is 
treated as (plus @0 @0), the pattern on the second occurence of the 
capture is silently ignored.


Regtested on ppc64le-redhat-linux.

2015-05-25  Marc Glisse  marc.gli...@inria.fr

* genmatch.c (write_predicate): Add ATTRIBUTE_UNUSED.
* match.pd (A op 0 ? A : -A, A op 0 ? A : 0): New simplifications.
* fold-const.c (fold_cond_expr_with_comparison): Remove
corresponding code.

--
Marc GlisseIndex: gcc/fold-const.c
===
--- gcc/fold-const.c(revision 223630)
+++ gcc/fold-const.c(working copy)
@@ -4875,112 +4875,25 @@ merge_ranges (int *pin_p, tree *plow, tr
Return a folded expression whose code is not a COND_EXPR
anymore, or NULL_TREE if no folding opportunity is found.  */
 
 static tree
 fold_cond_expr_with_comparison (location_t loc, tree type,
tree arg0, tree arg1, tree arg2)
 {
   enum tree_code comp_code = TREE_CODE (arg0);
   tree arg00 = TREE_OPERAND (arg0, 0);
   tree arg01 = TREE_OPERAND (arg0, 1);
-  tree arg1_type = TREE_TYPE (arg1);
   tree tem;
 
   STRIP_NOPS (arg1);
   STRIP_NOPS (arg2);
 
-  /* If we have A op 0 ? A : -A, consider applying the following
- transformations:
-
- A == 0? A : -Asame as -A
- A != 0? A : -Asame as A
- A = 0? A : -Asame as abs (A)
- A  0?  A : -Asame as abs (A)
- A = 0? A : -Asame as -abs (A)
- A  0?  A : -Asame as -abs (A)
-
- None of these transformations work for modes with signed
- zeros.  If A is +/-0, the first two transformations will
- change the sign of the result (from +0 to -0, or vice
- versa).  The last four will fix the sign of the result,
- even though the original expressions could be positive or
- negative, depending on the sign of A.
-
- Note that all these transformations are correct if A is
- NaN, since the two alternatives (A and -A) are also NaNs.  */
-  if (!HONOR_SIGNED_ZEROS (element_mode (type))
-   (FLOAT_TYPE_P (TREE_TYPE (arg01))
- ? real_zerop (arg01)
- : integer_zerop (arg01))
-   ((TREE_CODE (arg2) == NEGATE_EXPR
-   operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
-/* In the case that A is of the form X-Y, '-A' (arg2) may
-   have already been folded to Y-X, check for that. */
- || (TREE_CODE (arg1) == MINUS_EXPR
-  TREE_CODE (arg2) == MINUS_EXPR
-  operand_equal_p (TREE_OPERAND (arg1, 0),
- TREE_OPERAND (arg2, 1), 0)
-  operand_equal_p (TREE_OPERAND (arg1, 1),
- TREE_OPERAND (arg2, 0), 0
-switch (comp_code)
-  {
-  case EQ_EXPR:
-  case UNEQ_EXPR:
-   tem = fold_convert_loc (loc, arg1_type, arg1);
-   return pedantic_non_lvalue_loc (loc,
-   fold_convert_loc (loc, type,
- negate_expr (tem)));
-  case NE_EXPR:
-  case LTGT_EXPR:
-   return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, 
arg1));
-  case UNGE_EXPR:
-  case UNGT_EXPR:
-   if (flag_trapping_math)
- break;
-   /* Fall through.  */
-  case GE_EXPR:
-  case GT_EXPR:
-   if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
- arg1 = fold_convert_loc (loc, signed_type_for
-  (TREE_TYPE (arg1)), arg1);
-   tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
-   return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
-  case UNLE_EXPR:
-  case