[PATCH] generalized range_query class for multiple contexts

Andrew MacLeod amacleod@redhat.com
Tue Nov 10 01:57:24 GMT 2020


On 11/5/20 2:29 PM, Martin Sebor wrote:
> On 10/1/20 11:25 AM, Martin Sebor wrote:
>>
>
> I have applied the patch and ran some tests.  There are quite
> a few failures (see the list below).  I have only looked at
> a couple.  The one in in gcc.dg/tree-ssa/builtin-sprintf-warn-3.c
> boils down to the following test case.  There should be no warning
> for either sprintf call.  The one in h() is a false positive and
> the reason for at least some of the regressions.  Somehow,
> the conversions between int and char are causing Ranger to lose
> the range.
>
> $ cat t.c && gcc -O2 -S -Wall t.c
> char a[2];
>
> extern int x;
>
> signed char f (int min, int max)
> {
>   signed char i = x;
>   return i < min || max < i ? min : i;
> }
>
> void ff (signed char i)
> {
>   __builtin_sprintf (a, "%i", f (0, 9));   // okay
> }
>
> signed char g (signed char min, signed char max)
> {
>   signed char i = x;
>   return i < min || max < i ? min : i;
> }
>
> void gg (void)
> {
>   __builtin_sprintf (a, "%i", g (0, 9));   // bogus warning
> }
>


The latest changes resolve the issues witg the gg() case.
you will now get a range of [0,9] for the temporary:
=========== BB 4 ============
     <bb 4> :
     # iftmp.3_10 = PHI <0(2), i_6(3)>
     _2 = (int) iftmp.3_10;
     __builtin_sprintf (&a, "%i", _2);
     return;

_2 : int [0, 9]
iftmp.3_10 : signed char [0, 9]




The code issued for the 2 routines is very different. The first routine 
produces:

  =========== BB 2 ============
     <bb 2> :
     x.0_4 = x;
     i_6 = (signed char) x.0_4;
     _7 = (int) i_6;
     if (_7 < 0)
       goto <bb 4>; [50.00%]
     else
       goto <bb 3>; [50.00%]

_7 : int [-128, 127]
2->4  (T) x.0_4 :       int [-INF, -257][-128, -1][128, +INF]
2->4  (T) i_6 :         signed char [-INF, -1]
2->4  (T) _7 :  int [-128, -1]
2->3  (F) x.0_4 :       int [-INF, -129][0, 127][256, +INF]
2->3  (F) i_6 :         signed char [0, +INF]
2->3  (F) _7 :  int [0, 127]

=========== BB 3 ============
i_6     signed char [0, +INF]
_7      int [0, 127]
     <bb 3> :
     if (_7 > 9)
       goto <bb 4>; [50.00%]
     else
       goto <bb 5>; [50.00%]

3->4  (T) _7 :  int [10, 127]
3->5  (F) _7 :  int [0, 9]

=========== BB 4 ============
     <bb 4> :

=========== BB 5 ============
     <bb 5> :
     # iftmp.1_9 = PHI <i_6(3), 0(4)>
     _2 = (int) iftmp.1_9;
     __builtin_sprintf (&a, "%i", _2);
     return;

_2 : int [0, 127]
iftmp.1_9 : signed char [0, +INF]


Note that we figure out that _7 is [0,9] from 3->5,  except the PHI node 
in block 5 refers to i_6...

i_6 is not referred to in BB3, so this generation of ranger doesnt see 
it as an exportable value, and thus doesnt do a calculation for it like 
it does in BB2, where it is defined.  So it only picks up the first of 
the 2 conditions for i_6 that is live on entry to BB3 ([0, +INF])

2 things are in the pipe which will resolve this
1 - equivalences.  _7 is a cast-copy of i_6.  since the range of _7 
falls within the range of a signed char, the forthcoming 
equivalency/relational work will have i_6 match the same value as _7.
2 - The next generation GORI engine will allow for recalculation of 
dependency chains from outside the block when appropriate, so this will 
cause i_6 to also be an exportable value from BB 3 as well. which will 
also then get the [0,9] range in circumstances in which it isnt a simply 
copy.


Neither of which helps you right now with the perfect precision  :-P

Andrew




More information about the Gcc-patches mailing list