Optimization correct?

D

Dirk Zabel

Hi,
I have a function to put out a byte to the i2c-bus. We are on an
embedded system here, the code is generated by a tool.

static int i2c_write_byte(unsigned char by)
{
card Data9th;
int rval;
/* [...] lot of stuff omitted here for brevity */

/*--- Dummy read to reset RI flag ---*/
by = U0RB;

return rval;

}
U0RB is some processor-specific control register and is defined as:

#define MA_UNSIGNED_SHORT *(volatile unsigned short *)
#define U0RB (MA_UNSIGNED_SHORT ( 0x03A6 ))

The read access changes the state of the U0RB register.

When I compile this function with space optimazation turned on, the
dummy read gets optimized out. Question: what is wrong, the code or the
compiler? Should the volatile attribute have prevented the compiler from
discarding the read access?

Thanks for answers
-- Dirk
 
J

jacob navia

Le 27/10/10 18:56, Dirk Zabel a écrit :
Hi,
I have a function to put out a byte to the i2c-bus. We are on an
embedded system here, the code is generated by a tool.

static int i2c_write_byte(unsigned char by)
{
card Data9th;
int rval;
/* [...] lot of stuff omitted here for brevity */

/*--- Dummy read to reset RI flag ---*/
by = U0RB;

return rval;

}
U0RB is some processor-specific control register and is defined as:

#define MA_UNSIGNED_SHORT *(volatile unsigned short *)
#define U0RB (MA_UNSIGNED_SHORT ( 0x03A6 ))

The read access changes the state of the U0RB register.

When I compile this function with space optimazation turned on, the
dummy read gets optimized out. Question: what is wrong, the code or the
compiler? Should the volatile attribute have prevented the compiler from
discarding the read access?

Thanks for answers
-- Dirk

The value stored in "by" doesn't get used afterwards.
The variable "by" is not volatile, it is filled with a value retrieved
from a volatile variable.

I would propose that you store it in a volative variable

static int i2c_write_byte(unsigned char by)
{
card Data9th;
volatile short dummy;
int rval;
/* [...] lot of stuff omitted here for brevity */

/*--- Dummy read to reset RI flag ---*/
dummy = U0RB;

return rval;

}

jacob
 
B

Ben Bacarisse

Dirk Zabel said:
I have a function to put out a byte to the i2c-bus. We are on an
embedded system here, the code is generated by a tool.

static int i2c_write_byte(unsigned char by)
{
card Data9th;
int rval;
/* [...] lot of stuff omitted here for brevity */

/*--- Dummy read to reset RI flag ---*/
by = U0RB;

return rval;

}
U0RB is some processor-specific control register and is defined as:

#define MA_UNSIGNED_SHORT *(volatile unsigned short *)
#define U0RB (MA_UNSIGNED_SHORT ( 0x03A6 ))

The read access changes the state of the U0RB register.

When I compile this function with space optimazation turned on, the
dummy read gets optimized out. Question: what is wrong, the code or
the compiler? Should the volatile attribute have prevented the
compiler from discarding the read access?

I think the compiler must leave the access to the volatile object. In
fact, all you need is

U0RB;

without storing the result anywhere.

Can the compiler see a call to this static function? If the compiler is
sure that i2c_write_byte is not called, it may remove the whole thing.
Yes, that is not consistent with "the dummy read gets optimized out" but
it seems worth checking nonetheless.
 
S

Seebs

/*--- Dummy read to reset RI flag ---*/
by = U0RB;
U0RB is some processor-specific control register and is defined as:

#define MA_UNSIGNED_SHORT *(volatile unsigned short *)
#define U0RB (MA_UNSIGNED_SHORT ( 0x03A6 ))
The read access changes the state of the U0RB register.
When I compile this function with space optimazation turned on, the
dummy read gets optimized out. Question: what is wrong, the code or the
compiler? Should the volatile attribute have prevented the compiler from
discarding the read access?

Hmm. That's an interesting question. See, if you had a thing that
was volatile-qualified, I'd say sure, compiler's wrong. But you have
a thing which *isn't* volatile-qualified, which is then cast to a
volatile-qualified type, and I'm not sure whether that has the same effect.

I would be more comfortable with:

volatile unsigned short *u0rb = (unsigned short *) 0x03A6;
by = *u0rb;

-s
 
T

Tim Rentsch

Seebs said:
Hmm. That's an interesting question. See, if you had a thing that
was volatile-qualified, I'd say sure, compiler's wrong. But you have
a thing which *isn't* volatile-qualified, which is then cast to a
volatile-qualified type, and I'm not sure whether that has the same effect.

I would be more comfortable with:

volatile unsigned short *u0rb = (unsigned short *) 0x03A6;
by = *u0rb;

What he's doing should work. This technique is mentioned in
the Rationale for exactly this kind of case. Assigning the
address to an intermediate variable makes no difference
in terms of what object is accessed or what type it's
accessed with, so that should make no difference as to
whether the read can be optimized away.
 
S

Seebs

What he's doing should work. This technique is mentioned in
the Rationale for exactly this kind of case.

Theoretically, that's non-normative, but I concede the point.

Glad to hear that the standard actually says what I want it to say,
rather than what I'm afraid it might say. :)

-s
 
D

Dirk Zabel

Am 27.10.2010 19:30, schrieb Ben Bacarisse:
I think the compiler must leave the access to the volatile object. In
fact, all you need is

U0RB;

without storing the result anywhere.

Can the compiler see a call to this static function? If the compiler is
sure that i2c_write_byte is not called, it may remove the whole thing.
Yes, that is not consistent with "the dummy read gets optimized out" but
it seems worth checking nonetheless.

Yes, of course. There IS a call to this function; in fact the problem
arose that this function did not work correctly after the optimization
was enabled which was caused by the compiler optimizizg out the read
access to U0RB. It is simple enough to prevent this by putting the value
to another variable which is not known to be discarded, but this was not
my point. I simply wanted to know if the code was wrong or the compiler.
And this I want to know because I'm not sure who is to blame: the
compiler manufacture or the manufacturer of the code generator for the
processor-specific I/O.
Unfortunately, my code has grown so large that I cannot just stick with
unoptimized code, so I must know where I have to expect trouble.
In the meantime, I have found these citations from the draft of the C
language standard (I don't have access to the standard itself)

" An object that has volatile-qualified type may be modified in ways
unknown to the implementation or have other unknown side effects.
Therefore any expression referring to such an object shall be
evaluated strictly according to the rules of the abstract machine, as
described in $2.1.2.3.
Furthermore, at every sequence point the value
last stored in the object shall agree with that prescribed by the
abstract machine, except as modified by the unknown factors mentioned
previously./58/ What constitutes an access to an object that has
volatile-qualified type is implementation-defined."

The last sentence seems to be crucial to my problem: if "what
constitutes an access" is implementation-defined, one cannot decide if a
read-operation is an access in terms of the standard. So it depends on
the compiler implementation.

And the compiler reference manual says:
"Any reference to an object with volatile qualified type is an access."

So I would conclude: this as a compiler error. Not the only one,
unfortunately.

Regards
Dirk
 
T

Tim Rentsch

Seebs said:
Theoretically, that's non-normative,

Yes, and that's why I added the second sentence (which was
snipped) about what accesses are done and what types they
use -- I looked at the normative text as well as the
comment in the Rationale.
but I concede the point.

In neither case is the wording as clear as it could be,
but I think the intent comes through clearly enough.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top