12826 – [3.3 Regression] Optimizer removes reference through volatile pointer (original) (raw)

Description Lee Merrill 2003-10-29 14:50:12 UTC

(Using standard gcc shipped with RedHat 7.3 Linux)

$ gcc -v -save-temps -O -S t.c Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs gcc version 2.96 20000731 (Red Hat Linux 7.3 2.96-113) /usr/lib/gcc-lib/i386-redhat-linux/2.96/cpp0 -lang-c -v -D__GNUC__=2 -D__GNUC_MINOR__=96 -D__GNUC_PATCHLEVEL__=0 -D__ELF__ -Dunix -Dlinux -D__ELF__ -D__unix__ -D__linux__ -D__unix -D__linux -Asystem(posix) -D__OPTIMIZE__ -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -D__tune_i386__ t.c t.i GNU CPP version 2.96 20000731 (Red Hat Linux 7.3 2.96-113) (cpplib) (i386 Linux/ELF) ignoring nonexistent directory "/usr/i386-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/local/include /usr/lib/gcc-lib/i386-redhat-linux/2.96/include /usr/include End of search list. /usr/lib/gcc-lib/i386-redhat-linux/2.96/cc1 t.i -quiet -dumpbase t.c -O -version -o t.s GNU C version 2.96 20000731 (Red Hat Linux 7.3 2.96-113) (i386-redhat-linux) compiled by GNU C version 2.96 20000731 (Red Hat Linux 7.3 2.96-113).

Expected behavior: Should not optimize out the read of *sp in the loop. Actual behavior: Doesn't read *sp in the loop.

Comment 2 Falk Hueffner 2003-10-29 15:04:49 UTC

As I see it, *sp is not volatile, even if you access it with a pointer to volatile. It's the volatility of the object that counts. So IMHO this is not a bug.

Comment 3 Lee Merrill 2003-10-29 16:00:11 UTC

Thanks for your reply, cdecl gives me:

cdecl> explain volatile char *sp declare sp as pointer to volatile char

Which is what I want, a volatile char which should be read every time via sp. If I declare sp as "volatile char *" the code reads *sp as expected. It just seems that a cast should be equivalent to a declaration here...

Lee

P.S. Changing the assignment of "sp = 0xE8" to " (volatile char *) sp = 0xE8" also fixes the problem, which seems kind of odd.

Comment 4 Wolfgang Bangerth 2003-10-29 16:16:15 UTC

I agree with Falk. Of course, volatile char * is a pointer to a volatile char, but you are accessing a non-volatile object through a pointer to a volatile char. That doesn't change the non-volatility of the object and gcc should be free to optimize away the access. If you want to retain the read in the loop, declare the object as volatile.

W.

Comment 5 falk.hueffner 2003-10-29 16🔞44 UTC

Subject: Re: Optimizer removes reference through volatile pointer

"lee at bustech dot com" <gcc-bugzilla@gcc.gnu.org> writes:

Thanks for your reply, cdecl gives me:

cdecl> explain volatile char *sp declare sp as pointer to volatile char

Which is what I want, a volatile char which should be read every time via sp. If I declare sp as "volatile char *" the code reads *sp as expected. It just seems that a cast should be equivalent to a declaration here...

It's not. Or would you also expect:

int x = 3, *p = &x; f((const int *) p); x = 4;

to be rejected by the compiler? As I said, it's the volatility of the object that is relevant.

P.S. Changing the assignment of "sp = 0xE8" to " (volatile char *) sp = 0xE8" also fixes the problem, which seems kind of odd.

I wouldn't rely on that.

Comment 6 Lee Merrill 2003-10-29 16:39:16 UTC

... you are accessing a non-volatile object through a pointer to a volatile char. That doesn't change the non-volatility of the object

But it does change the object's volatility to change the assignment of "sp = 0xE8" to " (volatile char *) sp = 0xE8". Gcc should at least be consistent here, it seems...

As I said, it's the volatility of the object that is relevant.

I'm not sure what you mean here, the char is what I want to be volatile, and the cast seems to express that for me.

Thanks, Lee

Comment 7 Wolfgang Bangerth 2003-10-29 17:10:57 UTC

But it does change the object's volatility to change the assignment of "sp = 0xE8" to " (volatile char *) sp = 0xE8".

No, it doesn't. The type of a variable is a static quantity and not changed by how you assign a value to it. You declared sp to be non-volatile, so it will always be non-volatile.

Gcc should at least be consistent here, it seems...

gcc is missing a chance to optimize. That's not a bug.

I'm not sure what you mean here, the char is what I want to be volatile,

Then declare it to be volatile!

W.

Comment 8 falk.hueffner 2003-10-29 17:11:55 UTC

Subject: Re: Optimizer removes reference through volatile pointer

"lee at bustech dot com" <gcc-bugzilla@gcc.gnu.org> writes:

... you are accessing a non-volatile object through a pointer to a volatile char. That doesn't change the non-volatility of the object

But it does change the object's volatility to change the assignment of "sp = 0xE8" to " (volatile char *) sp = 0xE8". Gcc should at least be consistent here, it seems...

It doesn't change the object's volatility; it only inhibits an optimization. The optimizers don't work well in the presence of volatile, and in this particular case, I don't believe it's worth improving them.

As I said, it's the volatility of the object that is relevant.

I'm not sure what you mean here, the char is what I want to be volatile, and the cast seems to express that for me.

But it doesn't, as I've explained. Why didn't the example with "const" convince you?

Comment 9 Richard Henderson 2003-11-09 07:08:27 UTC

I don't agree that this is invalid. I don't see this as any different from

void f(signed char *sp) { int status; *sp = -1; status = *(unsigned char *) sp; if (status < 0) abort (); }

Comment 10 Drea Pinski 2003-11-09 18:50:27 UTC

It works on the 3.3 branch but does not work the mainline (20031108).

Comment 11 Drea Pinski 2003-11-09 18:59:13 UTC

On the mainline, the problem comes from the loop optimizer, .13.loop.

Comment 12 Drea Pinski 2003-11-29 21:35:53 UTC

It is jump bypass which is getting rid of the load.

Comment 13 Lee Merrill 2003-12-01 14:24:58 UTC

Subject: Re: [3.4 Regression] Optimizer removes reference through volatile pointer

pinskia at gcc dot gnu dot org wrote:

------- Additional Comments From pinskia at gcc dot gnu dot org 2003-11-29 21:35 ------- It is jump bypass which is getting rid of the load.

Thanks for your work on this...

Lee

Comment 14 Drea Pinski 2003-12-20 04:00:28 UTC

It was busted on the mainline: betweem 3.3 20020914 and 3.3 20020921.

Comment 18 Drea Pinski 2004-01-12 17:29:22 UTC

Only a 3.3.3 Regression now.

Comment 20 Gabriel Dos Reis 2004-01-21 02:42:12 UTC

Backported patch from mainline