https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110932
Andrew Pinski changed:
What|Removed |Added
Status|UNCONFIRMED |NEW
Ever confirmed|0 |1
Last reconfirmed||2023-08-19
--- Comment #1 from Andrew Pinski ---
_41 = _43 <= 0;
# RANGE [irange] unsigned short [0, 1] NONZERO 0x1
_40 = (unsigned short) _41;
# RANGE [irange] unsigned short [65534, +INF]
_36 = ~_40;
# RANGE [irange] short int [-2, -1]
_19 = (short intD.17) _36;
# RANGE [irange] unsigned int [4294967294, +INF]
_17 = (unsigned intD.9) _19; // ~(unsigned)_41
// rather _41 ? 4294967294 : 4294967295
i.1_14 = (unsigned intD.9) pretmp_60;
_13 = i.1_14 < _17;
# RANGE [irange] int [0, 1] NONZERO 0x1
_12 = (intD.6) _13;
if (_12 == pretmp_60)
pretmp_60 == (((unsigned intD.9) pretmp_60) < _17)
Which is:
(pretmp_60 == 1 && ((unsigned intD.9) pretmp_60) < _17))
| (pretmp_60 == 0 && ((unsigned intD.9) pretmp_60) >= _17))
Though ((unsigned intD.9) pretmp_60) >= _17) is always false because _17's
range does not include 0.
So we are left with:
(pretmp_60 == 1 && 1 < _17)
But _17's range is always bigger than 0 so we are just left with:
pretmp_60 == 1
So the general rule is:
(simplify
(eq:c @0 (convert (cmp @1 @2)))
(if (bitwise_equal_p (@0, @1))
(with {
bool zeroalwaystrue = ...
bool zeroalwaysfalse = ...
bool onealwaystrue = ...
bool onealwaysfalse = ...
}
(switch
(if (zeroalwaystrue && onealwaystrue)
(le @0:unsigned { one(unsigned); } )) // @0 == 0 | @0 == 1
(if (zeroalwaysfalse && onealwaysfalse )
{ false_bool; }) // false
(if (zeroalwaystrue && onealwaysfalse)
(eq @0 { zero(TREE_TYPE(@0)); })) // @0 == 0
(if (onealwaystrue && onealwaysfalse)
(eq @0 { one(TREE_TYPE(@0)); })) // @0 == 1
Later on instead of `if (_12 == _50)` we would have `if (_50 == 1)`
```
if (_50 == 1)
goto ; [51.12%]
else
goto ; [48.88%]
...
[local count: 278223726]:
if (_50 != 0)
goto ; [33.00%]
else
goto ; [67.00%]
```
Which is an obvious case where we know _50 is 1 in bb 4 and therefore !=0.
etc.