| Summary: | optimization dependant on condition order | ||
|---|---|---|---|
| Product: | gcc | Reporter: | denis.campredon |
| Component: | tree-optimization | Assignee: | Not yet assigned to anyone <unassigned> |
| Status: | NEW --- | ||
| Severity: | enhancement | CC: | amacleod, dimhen |
| Priority: | P3 | Keywords: | missed-optimization |
| Version: | 11.0 | ||
| Target Milestone: | --- | ||
| Host: | Target: | ||
| Build: | Known to work: | ||
| Known to fail: | Last reconfirmed: | 2021-07-19 00:00:00 | |
| Bug Depends on: | |||
| Bug Blocks: | 85316 | ||
This is because symbolic range handling sometimes throws away the symbolic equivalence I think. OTOH we have equivalences for this (but they are not always used, and with ranger all but the symbolic cases can be handled with multi-entry ranges) Confirmed. I Noticed that LLVM does not even optimize f3. Although we are now adding relations for these expressions, onc extension we have not gotten to apply ranges of relations. ie:
<bb 2> :
_1 = j_5(D) > i_6(D);
_2 = i_6(D) > 100;
_3 = _1 | _2;
if (_3 != 0)
goto <bb 3>; [INV]
else
goto <bb 4>; [INV]
2->3 (T) _3 : bool [1, 1]
2->4 (F) _1 : bool [0, 0]
2->4 (F) _2 : bool [0, 0]
2->4 (F) _3 : bool [0, 0]
2->4 (F) i_6(D) : int [-INF, 100]
Relational : (j_5(D) <= i_6(D))
<bb 4> :
if (j_5(D) > 100)
goto <bb 5>; [INV]
else
goto <bb 6>; [INV]
4->5 (T) j_5(D) : int [101, +INF]
4->6 (F) j_5(D) : int [-INF, 100]
We know that j_5 is <= i_6 on the edge 2->4, but we do not apply any known range of i_6 to j_5.
We do transitive between symbolics, ie (j < x && x < y means j < y)
We do not yet do that with a range as this requires. ie:
j_5 <= i_6, i_6 <= 100 means j <= 100
This will be an enhancement for the next release.
> void f4(signed int i,unsigned int j) {
> if (i > 100) return;
> if (j > i) return;
>
> if (j > 100) link_error();
if i is -2 (0xfffffffe) and j is 0xffffffffff (-1)
then link error cant be removed.. ?
(In reply to Andrew Macleod from comment #4) > > void f4(signed int i,unsigned int j) { > > if (i > 100) return; > > if (j > i) return; > > > > if (j > 100) link_error(); > > if i is -2 (0xfffffffe) and j is 0xffffffffff (-1) > > then link error cant be removed.. ? err, j is 0xfffffffd (-3) you get the idea :-) Friday evenings are killer for logic and bit patterns... |
In all the following functions gcc should recognize that j can't be greater than 100, and link_error should not appear in assembly. Currently only f3 is optimized. ------------------- void link_error(); void f1(int i, int j) { if (j > i || i > 100) return; if (j > 100) link_error(); } void f2(int i, int j) { if (i > 100 || j > i) return; if (j > 100) link_error(); } void f3(int i, int j) { if (i > 100) return; if (j > i) return; if (j > 100) link_error(); } void f4(signed int i,unsigned int j) { if (i > 100) return; if (j > i) return; if (j > 100) link_error(); } ------------------