This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Improve PR30911 and PR31023, Ada and VRP


Hi Eric,

> > With this fixed we can remove most of the range checking code
> > that Ada emits for the testcase in PR30911 if we pre-seed
> > parameter value-ranges in VRP with their types range.  This
> > should be immune against other bugs in fold and safe as Ada
> > ensures parameters are in range by checking code at the caller
> > site.
> 
> The latter assertion is not true for GNAT and, consequently, you cannot 
> pre-seed parameter ranges like that.

it is true it is not correct, but does it matter?  Ada has two classes
of errors: bounded errors (for example: a value is not in the range of
its type) and unbounded errors ("erroneous", for example: accessing off
the end of an array).  My understanding is that bounded errors are allowed
to cause other bounded errors, but are not allowed to escalate into
unbounded errors.

Suppose the type of X has range 1 .. 10, and A is an array with elements
in the range 1 .. 10.  The compiler inserts a check when doing A(X) that
must raise an exception if X is not in the range 1 .. 10; not doing so
would turn the bounded error of X not being in range into an unbounded error.

How is this check performed?  If the compiler simply generated:

  if X < 1 or X > 10 then
    raise_exception;
  end if;
  A(X)

then allowing VRP to assume that X is in the range 1 .. 10 would wrongly
remove this important check.  This is in fact how the Ada f-e implemented this
check historically.  However I thought the plan was to use VIEW_CONVERT_EXPR
to implement the check as this instead:

  Y = VIEW_CONVERT_EXPR(X, base_type);
  if Y < 1 or Y > 10 then
    raise_exception;
  end if;
  A(X);

In which case VRP will not remove the check because VIEW_CONVERT_EXPR is
a "VRP barrier".

If VIEW_CONVERT_EXPR was used for all checks that ensure that a bounded error
does not turn into an unbounded error, then teaching VRP that variables are in
the range of their types would not result in a bounded error escalating into an
unbounded error.  In particular, assuming that parameters are in the range of
their types would not result in the bounded error of them not being in range
turning into an unbounded error.

That said, it is not clear exactly what is allowed when there is a bounded
error.  For example, the Ada reference manual seems to require that uninitialized
values behave deterministically.  Suppose X is uninitialized (using it is then a
bounded error).  In the following code
  if X = 0 then
    do_something_with_X;
  end if;
must X have the value 0 in do_something_with_X?  My understanding that in C the
optimizers are allowed to say: since X is uninitialized, we may assume that it is
0, and always do_something_with_X.  This can result in doing do_something_with_X
when X is not 0.  If the type of X had the range 0 .. 0, then allowing VRP to
reason based on type ranges could likewise cause do_something_with_X to be executed
in the case of the bounded error of X containing an out of range value, i.e. not 0.
I think this was Bob Duff's point.

In fact, even without VRP this might be a problem: do gcc's constant propagation
passes turn
  ...X unitialized...
  if X = 0 then use_X; end if;
into
  if true then use_X; end if; (without X being "true" in use_X)
for example?

Ciao,

Duncan.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]