Bug 98026

Summary: optimization dependant on condition order
Product: gcc Reporter: denis.campredon
Component: tree-optimizationAssignee: 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    

Description denis.campredon 2020-11-27 10:04:35 UTC
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();
}
------------------
Comment 1 Richard Biener 2020-11-27 10:52:07 UTC
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)
Comment 2 Andrew Pinski 2021-07-19 04:17:57 UTC
Confirmed. I Noticed that LLVM does not even optimize f3.
Comment 3 Andrew Macleod 2022-01-12 19:34:35 UTC
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.
Comment 4 Andrew Macleod 2022-01-28 23:15:48 UTC
> 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.. ?
Comment 5 Andrew Macleod 2022-01-28 23:18:04 UTC
(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...