[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 --- Comment #6 from Andrew Pinski --- (In reply to Andrew Pinski from comment #4) > (In reply to Andrew Pinski from comment #3) > > Note we also don't optimize: > > > > inline int sign1(int x) > > { > > return (x < 0 ? -1 : 0) | (x > 0 ? 1 : 0); > > } > > bool f1(int x) > > { > > return sign1(x) < 1; > > } > > > > To be just `x <= 0` > > That is because forwprop leaves assignments that are not used anywhere still. > after dce7: > ``` > if (x_2(D) < 0) > goto ; [41.00%] > else > goto ; [59.00%] > >[local count: 633507680]: > _7 = x_2(D) != 0; > _8 = (int) _7; > _5 = _8 ^ 1; > _10 = (bool) _5; > >[local count: 1073741824]: > # prephitmp_11 = PHI <1(2), _10(3)> > ``` > After frowprop4: > ``` > if (x_2(D) < 0) > goto ; [41.00%] > else > goto ; [59.00%] > >[local count: 633507680]: > _7 = x_2(D) != 0; > _8 = (int) _7; > _3 = x_2(D) == 0; > _5 = (int) _3; > >[local count: 1073741824]: > # prephitmp_11 = PHI <1(2), _3(3)> > ``` > > If those statements were removed then phiopt4 would be able to optimize > prephitmp_11 to: `(x_2(D) < 0) | (x_2(D) == 0)` which simplifies to `x_2(D) > <= 0` . > > Let me look into the forwprop issue here. That was fixed with r14-3982-g9ea74d235c7e78 .
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 --- Comment #5 from Andrew Pinski --- (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).
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 Andrew Pinski changed: What|Removed |Added Assignee|unassigned at gcc dot gnu.org |pinskia at gcc dot gnu.org Status|NEW |ASSIGNED --- Comment #4 from Andrew Pinski --- (In reply to Andrew Pinski from comment #3) > Note we also don't optimize: > > inline int sign1(int x) > { > return (x < 0 ? -1 : 0) | (x > 0 ? 1 : 0); > } > bool f1(int x) > { > return sign1(x) < 1; > } > > To be just `x <= 0` That is because forwprop leaves assignments that are not used anywhere still. after dce7: ``` if (x_2(D) < 0) goto ; [41.00%] else goto ; [59.00%] [local count: 633507680]: _7 = x_2(D) != 0; _8 = (int) _7; _5 = _8 ^ 1; _10 = (bool) _5; [local count: 1073741824]: # prephitmp_11 = PHI <1(2), _10(3)> ``` After frowprop4: ``` if (x_2(D) < 0) goto ; [41.00%] else goto ; [59.00%] [local count: 633507680]: _7 = x_2(D) != 0; _8 = (int) _7; _3 = x_2(D) == 0; _5 = (int) _3; [local count: 1073741824]: # prephitmp_11 = PHI <1(2), _3(3)> ``` If those statements were removed then phiopt4 would be able to optimize prephitmp_11 to: `(x_2(D) < 0) | (x_2(D) == 0)` which simplifies to `x_2(D) <= 0` . Let me look into the forwprop issue here. 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.
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 --- Comment #3 from Andrew Pinski --- Note we also don't optimize: inline int sign1(int x) { return (x < 0 ? -1 : 0) | (x > 0 ? 1 : 0); } bool f1(int x) { return sign1(x) < 1; } To be just `x <= 0`
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 Andrew Pinski changed: What|Removed |Added Ever confirmed|0 |1 Last reconfirmed||2021-04-26 Status|UNCONFIRMED |NEW --- Comment #2 from Andrew Pinski --- Confirmed. Note the original code does have one slight undefined case, when x is INT_MIN but that can be fixed by casting to unsigned before doing the negate of x. That is: inline int sign(int x) { return (x >> 31) | (-(unsigned)x >> 31); } CUT Matching this: _1 = x_5(D) >> 31; x.0_2 = (unsigned int) x_5(D); _3 = -x.0_2; _4 = _3 >> 31; _8 = (int) _4; _6 = _1 | _8; Into: t = (int)(x > 0); result = x < 0 ? - 1 : t; Might not be the best thing.
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 Andrew Pinski changed: What|Removed |Added Severity|normal |enhancement
[Bug tree-optimization/94893] Sign function not getting optimized to simple compare
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94893 Gabriel Ravier changed: What|Removed |Added Target|x86_64-*-* | Blocks||19987 --- Comment #1 from Gabriel Ravier --- No idea why it was marked as x86-specific, it isn't as far as I can see, so I removed the target here. Do tell me if this is wrong. Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19987 [Bug 19987] [meta-bug] fold missing optimizations in general