On 6/19/19 11:04 PM, Kugan Vivekanandarajah wrote:
Hi Andrew,
Thanks for working on this.
Enable elimination of zext/sext with VRP patch had to be reverted in
(https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00672.html) due to the
need for value ranges in PROMOTED_MODE precision for at least 1 test
case for alpha.
Playing with ranger suggest that it is not possible to get value
ranges in PROMOTED_MODE precision on demand. Or is there any way we
can use on-demand ranger here?
Thanks,
Kugan
I took a look at the thread, but I think I'm still missing some context.
Lets go back to the beginning. What is an example of the case we arent
getting that you want to get?
I'm going to guess to start :-)
short foo(unsigned char c)
{
c = c & (unsigned char)0x0F;
if( c > 7 )
return((short)(c - 5));
else
return(( short )c);
}
A run of this thru the ranger shows me code that looks like (on x86 anyway):
=========== BB 2 ============
c_4(D) [0, 255] unsigned char
<bb 2> :
c_5 = c_4(D) & 15;
_9 = c_4(D) & 8;
if (_9 != 0)
goto <bb 3>; [INV]
else
goto <bb 4>; [INV]
c_5 : [0, 15] unsigned char
_9 : [0, 0][8, 8] unsigned char
2->3 (T)*c_5 : [0, 15] unsigned char
2->3 (T) _9 : [8, 8] unsigned char
2->4 (F)*c_5 : [0, 15] unsigned char
2->4 (F) _9 : [0, 0] unsigned char
=========== BB 3 ============
c_5 [0, 15] unsigned char
<bb 3> :
_1 = (unsigned short) c_5;
_2 = _1 + 65531;
_7 = (short int) _2;
// predicted unlikely by early return (on trees) predictor.
goto <bb 5>; [INV]
_1 : [0, 15] unsigned short
_2 : [0, 10][65531, 65535] unsigned short
_7 : [-5, 10] short int
=========== BB 4 ============
c_5 [0, 15] unsigned char
<bb 4> :
_6 = (short int) c_5;
// predicted unlikely by early return (on trees) predictor.
I think I see. we aren't adjusting the range of c_5 going into blocks 3
and 4. its obvious from the original source where the code says < 7,
but once its been "bitmasked" that info becomes obfuscated.
.
If you were to see a range in bb3 of c_5 = [8,15], and a range in bb4 of
c_4 = [0,7], would that solve your problem?
so in bb3 , we'd then see ranges that look like:
_1 : [8, 15] unsigned short
_2 : [3, 10] unsigned short
_7 : [3, 10] short int
and then later on we'd see there is no negative/wrap value, and you
could could just drop the extension then?
SO.
yes. this is fixable, but is it easy? :-)
We're in the process of replacing the range extraction code with the
range-ops/gori-computes components from the ranger. This is the part
which figures ranges out from individual statements on exit to a block..
We have implemented mostly the same functionality of VRP to start, and
one of the things we have not done is enhanced the bitmask tracking side
of it.
The gori-computes component which performs backwards calculations does
virtually nothing with masks right now.
lets look at this hunk
c_5 = c_4(D) & 15;
_9 = c_4(D) & 8;
if (_9 != 0)
on the true side of this branch, we start with _9 having a range of
[0,0][8,8]
[0,0][8,8] = c_4(D) & 8
unfortunately we dont know much about c_4, its effectively VARYING at
this point. We do know c_5 has a range of [0,15]. if that statement were
_9 = c_5 & 8
this problem would be quite trivial A quick tweak to the windback
code for bitwise_and would generate the correct results because we';d see
[1,1] = [0,15] & 8 and we'd come up with [8, 15] for c_5 no problem.
but its not.
I do have some "re-evalaution" code in the ranger which is only in the
proof of concept stages which might solve this problem down the road.
what the re-evlaution code does is look at the any changes to ranges
which are in the definition chain of the ssa-name you are looking at.
going back to the example again:
c_5 = c_4(D) & 15;
_9 = c_4(D) & 8;
if (_9 != 0)
_1 = (unsigned short) c_5; <<--- here.
When we ask for the range of c_5 here, we calculate the range normally
and come up with [0,15].
The re-evalution code then takes a look and notices that c_5 is also
dependent on the value of c_4 , and queries if the range of c_4 changed
at this point.
Well, we can know the value of c_4 must have the 0x8 bit set in this
block. This can be fed into a "re-evaluation" of c_5, and also then
know that c_5 must also have the 0x8 bit set.
THis would then reduce the calculated range from the original [0,15] to
a range of [8, 15]
So the mechanisms within the new code are sort of there, but they have
not been flushed out. THis will require
a) the re-evaluation code to be completed. Im not sure if it can be
applied within EVRP (It seems it should be possible) or whether it
requires the ranger.
b) some level of integration of bitfields with the range info so we
can also track bits set and cleared along with the range, and integrate
them with the calculations.
SO assuming I have been working on the correct problem here, No. we dont
get this now.
Once we get the range-ops and gori-computes code integrated and working
with EVRP and the bitfield stuff, we can again take a look and see where
we stand. I will keep it in mind as a practical example of how we might
want to combine the information.
So revisit this in September maybe?
Or have i completely missed the mark of the problem you are trying to
solve? :-)
Andrew
PS
Your original question is
Playing with ranger suggest that it is not possible to get value
ranges in PROMOTED_MODE precision on demand. Or is there any way we
can use on-demand ranger here?
I'm not sure i follow completely why, but in theory it would be possible
to add code to the ranger to walk a definition list calculating ranges
in whatever precision you want
=========== BB 2 ============
c_4(D) [0, 255] unsigned char
<bb 2> :
c_5 = c_4(D) & 15;
_9 = c_4(D) & 8;
if (_9 != 0)
goto <bb 3>; [INV]
else
goto <bb 4>; [INV]
=========== BB 3 ============
c_5 [0, 15] unsigned char
<bb 3> :
_1 = (unsigned short) c_5;
_2 = _1 + 65531;
_7 = (short int) _2;
Im not sure how that would help? the root of the problem would appear
to be the range of c_5 is not properly calculated to be [8,15]. no
matter what precision you use, the [0,4] + 65531 part of the range is
still going to produce an undesireable set upper bit, and still require
the zext/sext?