[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-06-04 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #22 from Qi Feng  ---
Two more similar ones:

x <= y  &&  x == ( 0 or XXX_MIN ) -->  x == ( 0 or XXX_MIN )
x >= y  &&  x == ( UXXX_MAX or XXX_MAX )  -->  x == ( UXXX_MAX or XXX_MAX )

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-30 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #20 from Qi Feng  ---
I have tried to merge signed and unsigned together:

/* x >  y   &&   x != ( 0 or XXX_MIN )   -->   x > y */
(for and (truth_and bit_and)
 (simplify
  (and:c (gt:c@3 @0 @1) (ne @0 INTEGER_CST@2))
  (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)))
   (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1))
&& integer_zerop (@2))
|| (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1))
&& wi::eq_p (wi::to_wide (@2),
 wi::min_value (TYPE_PRECISION (TREE_TYPE (@2)),
SIGNED
@3

/* x >  y  ||  x != ( 0 or XXX_MIN )   -->  x != ( 0 or XXX_MIN ) */
(for or (truth_or bit_ior)
 (simplify
  (or:c (gt:c @0 @1) (ne@3 @0 INTEGER_CST@2))
  (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)))
   (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1))
&& integer_zerop (@2))
|| (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1))
&& wi::eq_p (wi::to_wide (@2),
 wi::min_value (TYPE_PRECISION (TREE_TYPE (@2)),
SIGNED
@3

/* x <  y  &&  x != ( UXXX_MAX or XXX_MAX )  -->  x < y */
(for and (truth_and bit_and)
 (simplify
  (and:c (lt:c@3 @0 @1) (ne @0 INTEGER_CST@2))
  (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && INTEGRAL_TYPE_P (TREE_TYPE(@1)))
   (if ((TYPE_UNSIGNED (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@1))
&& wi::eq_p (wi::to_wide (@2),
 wi::max_value (TYPE_PRECISION (TREE_TYPE (@2)),
UNSIGNED)))
|| (!TYPE_UNSIGNED (TREE_TYPE(@0)) && !TYPE_UNSIGNED (TREE_TYPE(@1))
&& wi::eq_p (wi::to_wide (@2),
 wi::max_value (TYPE_PRECISION (TREE_TYPE (@2)),
SIGNED
@3

(That's not all of them, for that would be too long and I think it's not
necessary.)

I also tried it on a x86 laptop, seems it does work. But I got a bootstrap
issue. I don't know if it's caused by my patch or the version of gcc I used to
compile.

Another problem is that I can't craft some c/c++ code to test truth_and. Maybe
it's used by other languages? Is it necessary to use truth_and along side
bit_and?

I have to make this work on a ppc64le machine, could you give me some hints of
where to look into?

BTW, the following tests may be useful if you want test it on your machine:

#include 
/* x >  y   &&   x != ( 0 or INT_MIN )   -->   x > y */

_Bool f0 (unsigned x, unsigned y)
{
  return x >  y  &&  x != 0;
}

_Bool f1 (unsigned x, unsigned y)
{
  return y <  x  &&  x != 0;
}

_Bool f2 (unsigned x, unsigned y)
{
  return x != 0  &&  x >  y;
}

_Bool f3 (unsigned x, unsigned y)
{
  return x != 0  &&  y <  x;
}

_Bool f4 (int x, int y)
{
  return x >  y  &&  x != INT_MIN;
}

_Bool f5 (int x, int y)
{
  return y <  x  &&  x != INT_MIN;
}

_Bool f6 (int x, int y)
{
  return x != INT_MIN  &&  x >  y;
}

_Bool f7 (int x, int y)
{
  return x != INT_MIN  &&  y <  x;
}

_Bool f8 (unsigned char x, unsigned char y)
{
  return x >  y && x != 0;
}

/* x >  y  ||  x != ( 0 or XXX_MIN )   -->  x != ( 0 or XXX_MIN ) */

_Bool f10 (unsigned x, unsigned y)
{
  return x >  y  ||  x != 0;
}

_Bool f11 (int x, int y)
{
  return x >  y  ||  x != INT_MIN;
}

_Bool f12 (unsigned char x, unsigned char y)
{
  return x >  y  ||  x != 0;
}

_Bool f13 (signed char x, signed char y)
{
  return x >  y  ||  x != SCHAR_MIN;
}

/* x <  y  &&  x != ( UXXX_MAX or XXX_MAX )  -->  x < y */

_Bool f20 (unsigned x, unsigned y)
{
  return x <  y  &&  x != UINT_MAX;
}

_Bool f21 (int x, int y)
{
  return x <  y  &&  x != INT_MAX;
}

_Bool f22 (unsigned char x, unsigned char y)
{
  return x <  y  &&  x != UCHAR_MAX;
}

_Bool f23 (signed char x, signed char y)
{
  return x <  y  &&  x != SCHAR_MIN;
}

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-26 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #18 from Qi Feng  ---
I only learned gcc for about 2 months, and I have to say that I don't fully
understand what you guys were saying. Is match.pd the right place to fix this
issue? Am I in the wrong direction?

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-24 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #14 from Qi Feng  ---
Checking .original and .optimized file is just a quick method I use to check
whether an optimization happened (if not happen in first and last pass,
probably it didn't happen).  I didn't mean or think the transform should happen
in these passes.

Using the second pattern, the result of transform already showed in .original
file, so I think it maybe happened earlier (like in GENERIC).

And I tried the first pattern again using a totally clean debug build
(bootstrap disabled), still didn't see the transformation happen.  I don't know
what went wrong. :(

(I tested it on a ppc64le machine, don't know if that matters)

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-23 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #11 from Qi Feng  ---
I tried 2 patterns for the following test

  /* 1. x >  y  &&  x != 0 --> x > y  */
  /* 2. y <  x  &&  x != 0 --> y < x  */
  /* 3. x != 0  &&  x >  y --> x > y  */
  /* 4. x != 0  &&  y <  x --> y < x  */

  _Bool f1 (unsigned x, unsigned y)
  {
return x >  y  &&  x != 0;
  }

  _Bool f2 (unsigned x, unsigned y)
  {
return y <  x  &&  x != 0;
  }

  _Bool f3 (unsigned x, unsigned y)
  {
return x != 0  &&  x >  y;
  }

  _Bool f4 (unsigned x, unsigned y)
  {
return x != 0  &&  y <  x;
  }

The first one is

  (for and (truth_and bit_and)
(simplify
 (and:c (gt:c@2 @0 @1) (ne @0 integer_zerop))
  (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0))
   && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1)))
   @2)))

The transformations did not happen as I checked the dump files of
-fdump-tree-{original,optimized}.

And the second one is

  (simplify
   (truth_andif:C (gt:c@2 @0 @1) (ne @0 integer_zerop))
(if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0))
 && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1)))
 @2))

The transformations did happen for all the 4 functions. And the dump of
-fdump-tree-original showes they already happened, so I guess the pattern is
matched before the process get to GIMPLE.

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-22 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #9 from Qi Feng  ---
And there's another problem. Take `x >  y  &&  x != 0   -->   x > y' for
example, I would also like to do

   x <  y  &&  y != 0  -->  x < y
   x != 0  &&  x >  y  -->  x > y
   y != 0  &&  x <  y  -->  x < y

If the constant always comes in as the second operand is incorrect, these would
have to be doubled.

I tried to add :c to truth_andif, but got the `operation is not commutative'
error.  I also tried to make truth_andif commutative by modifying genmatch.c,
but again, I don't know it well, afraid that I would break something.

The patterns I wrote looks like:

/* x >  y  &&  x != 0 --> x > y
   Only for unsigned x and y.  */
(simplify
 (truth_andif:c (gt@2 @0 @1) (ne @0 integer_zerop))
 (if (INTEGRAL_TYPE_P (TREE_TYPE(@0)) && TYPE_UNSIGNED (TREE_TYPE(@0))
  && INTEGRAL_TYPE_P (TREE_TYPE(@1)) && TYPE_UNSIGNED (TREE_TYPE(@1)))
   @2))

I have to wrote 4 of this with minor modification for a single transformation.
If there's better way to do it, please do leave a comment.

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-22 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #7 from Qi Feng  ---
I add some patterns in match.pd which handles the original 5 transformations.
But I don't the language used in match.pd well, the patterns I wrote are very
similar.

And I haven't found predicates for constant values other than zero (INT_MIN,
LONG_MIN, LLONG_MIN etc.).

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-22 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #5 from Qi Feng  ---
(In reply to Qi Feng from comment #4)
> The fourth to the last should be:
> 
>   x <  y   ||   x != INT_MAX -->   x != UINT_MAX
> 
> sorry for the typo.

   x <  y   ||   x != INT_MAX -->   x != INT_MAX

typo again...

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-22 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #4 from Qi Feng  ---
The fourth to the last should be:

  x <  y   ||   x != INT_MAX -->   x != UINT_MAX

sorry for the typo.

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-22 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

--- Comment #3 from Qi Feng  ---
I have extended the transformations as following, the first five are the
original ones:

* unsigned
  Use UINT_MAX for demonstration, similar for UCHAR_MAX, USHRT_MAX, UINT_MAX,
  ULONG_MAX, ULLONG_MAX

  x >  y   &&   x != 0   -->   x > y
  x >  y   ||   x != 0   -->   x != 0
  x <= y   ||   x != 0   -->   true
  x <= y   ||   x == 0   -->   x <= y
  x >  y   &&   x == 0   -->   false

  x <  y   &&   x != UINT_MAX-->   x < y
  x <  y   ||   x != UINT_MAX-->   x != UINT_MAX
  x >= y   ||   x != UINT_MAX-->   true
  x >= y   ||   x == UINT_MAX-->   x >= y
  x <  y   &&   x == UINT_MAX-->   false

* signed
  Use INT_MIN, INT_MAX for demonstration, similar for SCHAR_MIN, SHRT_MIN,
  INT_MIN, LONG_MIN, LLONG_MIN, SCHAR_MAX, SHRT_MAX, INT_MAX, LONG_MAX,
  LLONG_MAX

  x >  y   &&   x != INT_MIN -->   x > y
  x >  y   ||   x != INT_MIN -->   x != INT_MIN
  x <= y   ||   x != INT_MIN -->   true
  x <= y   ||   x == INT_MIN -->   x <= y
  x >  y   &&   x == INT_MIN -->   false

  x <  y   &&   x != INT_MAX -->   x < y
  x <  y   ||   x != INT_MAX -->   x != UINT_MAX
  x >= y   ||   x != INT_MAX -->   true
  x >= y   ||   x == INT_MAX -->   x >= y
  x <  y   &&   x == INT_MAX -->   false


Want to know if I missed something.

[Bug middle-end/88784] Middle end is missing some optimizations about unsigned

2019-05-06 Thread ffengqi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88784

Qi Feng  changed:

   What|Removed |Added

 CC||ffengqi at gcc dot gnu.org

--- Comment #2 from Qi Feng  ---
I tried some modifications in and_comparisons_1 and or_comparisons_1. It seems
that `||' is transformed to `&&' somewhere. And that makes the changes in
or_comparisons_1 noneffective. Should I find the place where the transformation
happens and make changes before that?