Is there a way to flush registers and tell the C compiler to refill?

Discussion in 'C Programming' started by Emmanuel Stapf [ES], Mar 19, 2009.

  1. Hi,

    Because using volatile would prevent some C compilation optimization,
    I'm looking at an alternative where I would inform the C compiler that
    from known points in my program code, no values are in registers and
    thus the generated code should refetch the data from memory (and then
    use register whenever it can).

    For example,

    struct complex_struct s {
    int value;
    };

    void f () {

    int i;

    i = s.value + s.value; /* 1 */

    routine_that_will_indirectly_modify_s_value(); /* 2 */

    i = s.value + s.value; /* 3 */

    }

    If the C compiler had optimized the access to `s.value' in a register in
    #1, I want to prevent the C compiler from using that register in #3
    because the value was externally modified in #2.

    If I was making volatile, then all accesses to `s.value' would be
    penalized and I don't want that.

    Thanks for the help,
    Manu
     
    Emmanuel Stapf [ES], Mar 19, 2009
    #1
    1. Advertising

  2. Re: Is there a way to flush registers and tell the C compiler torefill?

    Eric Sosman wrote:
    > It is the compiler's business to make sure that any modifications
    > routine...() might make to `s' will be visible to the rest of the
    > program. If the compiler allows /* 3 */ to ignore the new value of `s'
    > and use a "stale" value instead, the compiler is broken.


    Will you consider that a C compiler should always refetch `s.value'
    after #2 in this slightly modified sample?

    void f () {

    int i;
    struct complex_struct s {
    int value;
    };

    routine_storing_address_of_struct (&s);

    i = s.value + s.value; /* 1 */

    routine_modifying_s_value_via_recorded_address_above(); /* 2 */

    i = s.value + s.value; /* 3 */

    }

    Thanks,
    Manu
     
    Emmanuel Stapf [ES], Mar 19, 2009
    #2
    1. Advertising

  3. Emmanuel Stapf [ES]

    Lew Pitcher Guest

    On March 19, 2009 14:59, in comp.lang.c, Emmanuel Stapf [ES]
    () wrote:

    > Hi,
    >
    > Because using volatile would prevent some C compilation optimization,
    > I'm looking at an alternative where I would inform the C compiler that
    > from known points in my program code, no values are in registers and
    > thus the generated code should refetch the data from memory (and then
    > use register whenever it can).
    >
    > For example,
    >
    > struct complex_struct s {
    > int value;
    > };


    A question to the experts here...

    Is the above declaration even legal? Does it declare s to be of type "struct
    complex_struct"?

    AFAICT, the syntax of the declaration of s should be
    struct complex_type { int value; } s;
    conforming to the pattern of
    <type-specifier> <declarator>
    where
    <type-specifier>
    is a
    <struct-or-union-specifier>
    consisting of
    struct <identifier> { <struct-declaration-list> }

    The given declaration does not match the <struct-or-union-specifier>, in
    that it contains _two_ <identifier>s. Further, the whole statement does not
    conform to the <type-specifier> <declarator> pattern, as it lacks the
    <declarator> that follows the completed <type-specifier>.

    Is my understanding correct?

    --
    Lew Pitcher

    Master Codewright & JOAT-in-training | Registered Linux User #112576
    http://pitcher.digitalfreehold.ca/ | GPG public key available by request
    ---------- Slackware - Because I know what I'm doing. ------
     
    Lew Pitcher, Mar 19, 2009
    #3
  4. Re: Is there a way to flush registers and tell the C compiler torefill?

    Eric Sosman wrote:
    > Lew Pitcher wrote:
    >> On March 19, 2009 14:59, in comp.lang.c, Emmanuel Stapf [ES]
    >> () wrote:
    >>
    >>> Hi,
    >>>
    >>> Because using volatile would prevent some C compilation optimization,
    >>> I'm looking at an alternative where I would inform the C compiler that
    >>> from known points in my program code, no values are in registers and
    >>> thus the generated code should refetch the data from memory (and then
    >>> use register whenever it can).
    >>>
    >>> For example,
    >>>
    >>> struct complex_struct s {
    >>> int value;
    >>> };

    >>
    >> A question to the experts here...
    >>
    >> Is the above declaration even legal? Does it declare s to be of type
    >> "struct
    >> complex_struct"?
    >> [...]

    >
    > You're right: It's illegal (barring preprocessor tricks).
    > I'm sorry to say that I skimmed straight past it, reading it
    > as `struct complex_struct {...} s;', which is what I imagine
    > the O.P. actually intended. Good catch.


    My bad indeed.

    Manu
     
    Emmanuel Stapf [ES], Mar 19, 2009
    #4
  5. Emmanuel Stapf [ES]

    Walter Banks Guest

    "Emmanuel Stapf [ES]" wrote:

    > Hi,
    >
    > Because using volatile would prevent some C compilation optimization,
    > I'm looking at an alternative where I would inform the C compiler that
    > from known points in my program code, no values are in registers and
    > thus the generated code should refetch the data from memory (and then
    > use register whenever it can).
    >
    > For example,
    >
    > struct complex_struct s {
    > int value;
    > };
    >
    > void f () {
    >
    > int i;
    >
    > i = s.value + s.value; /* 1 */
    >
    > routine_that_will_indirectly_modify_s_value(); /* 2 */
    >
    > i = s.value + s.value; /* 3 */
    >
    > }
    >
    > If the C compiler had optimized the access to `s.value' in a register in
    > #1, I want to prevent the C compiler from using that register in #3
    > because the value was externally modified in #2.
    >
    > If I was making volatile, then all accesses to `s.value' would be
    > penalized and I don't want that.


    The data flow analysis should determine if the s is modified in
    routine_that_will_indirectly_modify_s_value which will flag the
    s.value as unknown after the function call. That would force
    s.value to be reloaded. In your simple example it is entirely possible
    that no code would be generated for #1 because i is not
    read until it is re-assigned.

    It would be rare for the global variable s to be allocated to
    processor registers in anything other than in trivial cases.
    "i" on the other hand may very likely be allocated to a register
    possibly two different registers in many cases for #1 and #3
    assuming a slightly more complex program that forced #1
    to generate code, for example passing i to the function a
    case that most likely would optimize the write to "i" in
    #1.

    i = s.value + s.value; /* 1 */
    routine_that_will_indirectly_modify_s_value(i); /* 2 */
    i = s.value + s.value; /* 3 */

    The short answer is I don't think in this example there is much
    danger the variable to register optimization in the compiler
    will cause undesired program behaviour.

    Regards,

    --
    Walter Banks
    Byte Craft Limited
    http://www.bytecraft.com
     
    Walter Banks, Mar 19, 2009
    #5
  6. Emmanuel Stapf [ES]

    Kaz Kylheku Guest

    Re: Is there a way to flush registers and tell the C compiler torefill?

    On 2009-03-19, Emmanuel Stapf [ES] <> wrote:
    > Hi,
    >
    > Because using volatile would prevent some C compilation optimization,
    > I'm looking at an alternative where I would inform the C compiler that
    > from known points in my program code, no values are in registers and
    > thus the generated code should refetch the data from memory (and then
    > use register whenever it can).


    There is no such interface in C. But using external functions may achieve this
    on many compilers.

    >
    > For example,
    >
    > struct complex_struct s {
    > int value;
    > };


    you mean:

    struct complex_struct { ... } s;

    > void f () {
    >
    > int i;
    >
    > i = s.value + s.value; /* 1 */
    >
    > routine_that_will_indirectly_modify_s_value(); /* 2 */
    >
    > i = s.value + s.value; /* 3 */
    >
    > }


    Note that if the routine modifes s in a correct, well-defined way, then there
    is nothing to worry about (other than a broken compiler). Such a caching
    optimization applied blindly is forbidden. A sequence point occurs immediately
    before the function call, and the function must see the stable value of object
    s. A sequence point occurs before the function returns also.

    So even if the aggressive caching is done, it must be done in such a way that
    the routine can see the cached value. If it cannot be ensured that the routine
    can used the cached value, then the caching cannot be done.

    But the name of your function hints at the fact that s is somehow manipulated
    indirectly, like through some aliased pointer or some such thing. In that case,
    you are on your own, because the behavior is undefined. The language has no
    interface by which you can say ``please do not cache this value''.

    However, what you may be able to rely on is making the function external to
    your translation unit, and also giving the variable s external linkage.
    These facts taken together will forbid most compilers from making any caching
    optimizations on s.

    This is because the external function has access to the variable and can change
    it arbitrarily.

    Caching s in spite of this would require global program optimization: code
    optimization and generation would have to be delayed until the point when the
    program is being linked, at which time it could be proven that the external
    function does not touch the variable, and the code could be optimized
    accordingly before the final link.

    Unless you have this kind of toolchain, this solution should be good enough.
    Most C compilers do a more or less complete job of generating the code in
    complete isolation, and the final linking stages only resolve the external
    references to objects and functions, without rewriting any code in any
    significant way.

    > If I was making volatile, then all accesses to `s.value' would be
    > penalized and I don't want that.


    volatile is a poorly-defined stupidity which should be confined to only the
    documented, required ISO C uses: declaring the type of a flag set by an
    asynchronous signal handler to be of type ``volatile sig_atomic_t'',
    and applying the volatile qualification on local variables that are modified
    between setjmp and longjmp whose values are used after the longjmp.
    volatile has no other uses that can be relied upon to be portable. For any
    specific assurances, you want to use the appropriate compiler extension, if you
    have it, or write in assembly language, etc.
     
    Kaz Kylheku, Mar 19, 2009
    #6
  7. Emmanuel Stapf [ES]

    Guest

    Re: Is there a way to flush registers and tell the C compiler torefill?

    On Mar 19, 1:59 pm, "Emmanuel Stapf [ES]"
    <> wrote:
    > Hi,
    >
    > Because using volatile would prevent some C compilation optimization,
    > I'm looking at an alternative where I would inform the C compiler that
    > from known points in my program code, no values are in registers and
    > thus the generated code should refetch the data from memory (and then
    > use register whenever it can).
    >
    > For example,
    >
    > struct complex_struct s {
    >         int value;
    >
    > };
    >
    > void f () {
    >
    >         int i;
    >
    >         i = s.value + s.value; /* 1 */
    >
    >         routine_that_will_indirectly_modify_s_value(); /* 2 */
    >
    >         i = s.value + s.value; /* 3 */
    >
    > }
    >
    > If the C compiler had optimized the access to `s.value' in a register in
    > #1, I want to prevent the C compiler from using that register in #3
    > because the value was externally modified in #2.
    >
    > If I was making volatile, then all accesses to `s.value' would be
    > penalized and I don't want that.



    One thing you can do is have a second copy of s.value, and use only
    those in the majority of your program. Make the original s.value
    volatile, and then copy any updates to both places, and in all the
    places you are proposing to flush registers, copy the original s.value
    to the working copy. Most compilers will probably generate a few
    additional stores for that code, but probably still better than doing
    all the loads forced by making the (only) copy of the variable
    volatile.

    If the variable is basically read only except in
    routine_that_will_indirectly_modify_s_value(), you basically need to
    load the working copy once at startup (by copying from the base copy),
    and then the assignments in r_t_w_i_m_s_v() will take care of the
    rest.
     
    , Mar 20, 2009
    #7
  8. Emmanuel Stapf [ES]

    Kaz Kylheku Guest

    Re: Is there a way to flush registers and tell the C compiler torefill?

    On 2009-03-22, JosephKK <> wrote:
    > I do not think that volatile has the same meaning to hardware that it
    > used to


    Used to? When was this, and what was the meaning?

    > the multilevel caches change the fundamentals of the mapping
    > between registers and memory that there used to be.


    Not from the point of view of a single processor, or even multiple processors
    when cache coherency is maintained. Also, memory-mapped I/O is typically in
    regions designated as uncached.

    But none of that changes the reality that volatile is a largely meaningless
    dongle in the language, and always has been.
     
    Kaz Kylheku, Mar 23, 2009
    #8
  9. Re: Is there a way to flush registers and tell the C compiler torefill?

    wrote:
    > One thing you can do is have a second copy of s.value, and use only
    > those in the majority of your program. Make the original s.value
    > volatile, and then copy any updates to both places, and in all the
    > places you are proposing to flush registers, copy the original s.value
    > to the working copy. Most compilers will probably generate a few
    > additional stores for that code, but probably still better than doing
    > all the loads forced by making the (only) copy of the variable
    > volatile.


    This is a good idea. I'll see what the trade off is.

    Regards,
    Manu
     
    Emmanuel Stapf [ES], Mar 24, 2009
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Samuel R. Neff
    Replies:
    1
    Views:
    362
    Juan T. Llibre
    Jan 23, 2007
  2. Metalone
    Replies:
    5
    Views:
    284
    Thomas Heller
    Oct 19, 2007
  3. aaragon
    Replies:
    4
    Views:
    308
    aaragon
    Nov 26, 2007
  4. Chris Roden
    Replies:
    4
    Views:
    592
    Mark Rae [MVP]
    Dec 13, 2007
  5. Merciadri Luca
    Replies:
    5
    Views:
    1,100
    Merciadri Luca
    Oct 14, 2010
Loading...

Share This Page