Re: Possible ANSI C Optimisation Done in Practice?

"David Thompson" <david.thompson1@worldnet.att.net>
27 Dec 2001 00:14:42 -0500

          From comp.compilers

Related articles
[11 earlier articles]
Re: Possible ANSI C Optimisation Done in Practice? nmm1@cus.cam.ac.uk (2001-12-22)
Re: Possible ANSI C Optimisation Done in Practice? ralph@inputplus.demon.co.uk (2001-12-22)
Re: Possible ANSI C Optimisation Done in Practice? ralph@inputplus.demon.co.uk (2001-12-24)
Re: Possible ANSI C Optimisation Done in Practice? nmm1@cus.cam.ac.uk (2001-12-24)
Re: Possible ANSI C Optimisation Done in Practice? toon@moene.indiv.nluug.nl (Toon Moene) (2001-12-24)
Re: Possible ANSI C Optimisation Done in Practice? nmm1@cus.cam.ac.uk (2001-12-27)
Re: Possible ANSI C Optimisation Done in Practice? david.thompson1@worldnet.att.net (David Thompson) (2001-12-27)
Re: Possible ANSI C Optimisation Done in Practice? david.thompson1@worldnet.att.net (David Thompson) (2002-01-03)
Re: Possible ANSI C Optimisation Done in Practice? ralph@inputplus.demon.co.uk (2002-01-05)
| List of all articles for this month |

From: "David Thompson" <david.thompson1@worldnet.att.net>
Newsgroups: comp.compilers
Date: 27 Dec 2001 00:14:42 -0500
Organization: AT&T Worldnet
References: 01-12-050 01-12-073
Keywords: optimize
Posted-Date: 27 Dec 2001 00:14:42 EST

Rodney M. Bates <rbates@southwind.net> wrote :
> Ralph Corderoy wrote:
....
> The following, sleazy program makes s overlap tmp:
[ by saving a pointer to local/stack space after return ]
....
> Not surprisingly, ANSI C says the behaviour is undefined when
> you do this. (6.2.4(2,5)) A compliant compiler is under no obligation
> to tell you about it, at compile time or runtime. But it can still
> make optimizations which depend on non-overlap of the strings and
> claim to be compliant.


Right.


> > and since t is initially assigned to tmp, and it isn't legal for t
> > to proceed past tmp + 10, assigning to *t can't be changing s.
>
> There is no way the rules of the language could prevent t from
> proceeding past tmp + 10, because the type system has already
> forgotten, by the time t = tmp; has been executed, that t points
> into array tmp. It's now just a pointer to a character, located
> anywere, within an array that is infinite in both directions.


They do prohibit it. In the C Standard (C99 6.5.6p8,9; C90 6.3.6) and
C++ (5.7[expr.add]p6-8) pointer arithmetic is well-defined only if the
result is still within the same array or just past its end, or just
after a scalar object (treated as array of 1); and _dereferencing_ an
off-end/just-past pointer is undefined. Violating this is undefined
behavior, as above, so diagnosing it is not required, and many if not
most implementations do allow pointer arithmetic through all of the
address space -- but are not required to, and a program depending on
such is not strictly conforming (a category so weak as to be arguably
useless anyway, see every few months on comp.std.c).


> Just call the original foo with a string longer than 10. Something
> will get stepped on, and you won't be able to explain it in C
> terms. Only a machine-level (and machine-dependent ) model will
> explain it. (This is also true of my program above.)


Exactly. Exceeding the array bound is also undefined behavior, so
anything the implementation does, including an optimization that
produces an unexpected and/or undesired result, is permitted, and no
diagnostic is required. And although catching such _is_ permitted by
the Standards, it is more difficult than for languages with
conventional array semantics, typically by using fat pointers or
memory tagging only in toy systems and some (usually inefficient)
debugging tools.


C also requires that an object can only legally be accessed with its
"proper" type (or very nearly so) or as individual bytes (C99 6.5, C90
6.3). This means that something like
    double foo = 1.23;
    printf("%ld\n", *(long *)&foo);
isn't actually required to work, so "type-aware" optimization
which breaks it, e.g. by keeping foo in a floating-point register
that can't support integer operations, is allowed. Last time
I investigated, which was quite a while ago, gcc did this
in at least some (more separated) cases.


And C99 adds a new qualifier 'restrict' which tells the compiler to
assume that otherwise compatible formals are not aliased (or rather,
since C has only call-by-value, that pointer formals point to
unaliased objects) and permit optimization accordingly, equivalent to
(and because of) what Fortran has always done. It is then the
programmer's responsibility to ensure that actuals are in fact
unaliased, the implementation is not required to even attempt to catch
violations, although again permitted.


--
- David.Thompson 1 now at worldnet.att.net


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.