https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893
--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #4) > As for the original issue: > x.0_5 = (unsigned int) x_2(D); > _6 = -x.0_5; > _7 = _6 >> 31; > _8 = (int) _7; > > We have a pattern for basically this: > /* Fold (-x >> C) into -(x > 0) where C = precision(type) - 1. */ > > But only for !TYPE_UNSIGNED here. we can do it for unsigned where we just > get x > 0 instead. I have a patch which gets us to: # RANGE [irange] int [-1, 0] _3 = x_2(D) >> 31; _5 = x_2(D) > 0; # RANGE [irange] int [0, 1] MASK 0x1 VALUE 0x0 _6 = (intD.9) _5; # RANGE [irange] int [-1, 1] _7 = _3 | _6; _4 = _7 != 1; (_3 | _6) != 1 means !((_3 == 0) && (_6 == 1)) since _3 can't be 1 at all. (_3 == 0) is x >= 0 and _6 == 1 is `x > 0` and that combines to be just `x >= 0` . I think the above only works if the two ranges in the _3|_6 is [-1,0] and [1,0] . (_3 | _6) == -1 just means _3 == -1 even which we don't handle either (and would be simplier to handle than other cases).