[Bug tree-optimization/112628] `~a < -a` can be optimized to `a != 0` for unsigned types

2023-11-19 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112628

--- Comment #2 from Andrew Pinski  ---
For signed, it is just true.

That is:
```
int f(int a)
{
  return (~a) < -a;
}
int f0(int a)
{
  return (a) > ~(-a);
}
```
Are the same.

In fact we can optimize even more:
```
int feq(int a)
{
  return (~a) == -a;
}
```
is always false for both signed and unsigned types.

So we just do `~a CMP -a` -> `(a - 1) CMP a` for all types.

Which is what we do for: `/* Fold ~X op ~Y as Y op X.  */`

So it is just
```
/* Fold ~X op -Y as (~(-Y)) op X. or `(Y-1) op X`  */
(for cmp (simple_comparison)
 (simplify
  (cmp:c (bit_not @0) (negative @1))
  (cmp (plus @1 { build_minus_one_cst (TREE_TYPE (@0)); }) @0)))
```

[Bug tree-optimization/112628] `~a < -a` can be optimized to `a != 0` for unsigned types

2023-11-19 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112628

Andrew Pinski  changed:

   What|Removed |Added

 Ever confirmed|0   |1
   Last reconfirmed||2023-11-19
 Status|UNCONFIRMED |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |pinskia at gcc dot 
gnu.org

--- Comment #1 from Andrew Pinski  ---
Note also we should be optimize this at the gimple level too:
```
unsigned f1(unsigned a, unsigned *c)
{
  return __builtin_add_overflow(a,-a,c);
}
```

into:
```
unsigned f1(unsigned a, unsigned *c)
{
  *c = 0;
  return a != 0;
}
```

Or the gimple level format:
```
  _1 = -a_4(D);
  _5 = .ADD_OVERFLOW (_1, a_4(D));
  _2 = REALPART_EXPR <_5>;
  *c_7(D) = _2;
  _3 = IMAGPART_EXPR <_5>;
```
Into:
```
_tmp = a != 0;
_5 = COMPLEX_EXPR<0, _tmp>;
...
```

Mine.