Disabling local optimizations with GCC

Christopher Bahns chris@bahns.com
Wed Jun 28 20:09:00 GMT 2000


Anyone know how to take advantage of most of GCC's optimizations without
it performing certain local optimizations? I read through the -O and -f
options in the gcc manual and did not see anything specifically just for
local optimizations. There is the "-fgcse" (global common
subexpressions) but I guess this would not apply to commonizing
subexpressions locally within a function... don't really know. I did not
see any "-flcse" or similar option.

Here's my problem:
I'm using a cross-compiler under Windows 98/NT for an m68k-coff target
(MC68306). I have certain symbols mapped to specific hardware addresses
so that I can interact with the hardware (as I assume most would do it).
In some cases I assign different values to the same address in
succession, or intermixed with the assignment of values to other
addresses. It is important for all assignments to occur because each one
causes the hardware to perform a particular action, and all actions need
to occur in the order I've placed them in the C-language functions. The
problem is that with any GCC optimization level  (-O, -O1, -O2, or -O3),
it "optimizes" out all but the last assignment to a given location. This
causes my program not to work. Everything seems to be fine if I disable
all optimizations, but some parts of my program are time-critical and I
may need some of the optimizations for the program to work right.

Of course, I can choose to disable all optimizations except the ones
that I specify explicitly with "-f" options, but I'd prefer to have as
many enabled as possible without breaking my program.

Here is some example code:
/* duart's base i/o address */
#define IoPortAddr   ((BYTE*)0xa0001)

void InitDuart681(void)
   /* disable transmitter and receiver */
   IoPortAddr[DUCRA] = ((0x0 << 4) | (0x2 << 2) | 0x2);
   IoPortAddr[DUCRB] = ((0x0 << 4) | (0x2 << 2) | 0x2);

   /* reset UartA transmitter and receiver */
   IoPortAddr[DUCRA] = (0x2 << 4);
   IoPortAddr[DUCRA] = (0x3 << 4);

   /* make sure we're not in break */
   IoPortAddr[DUCRA] = (0x7 << 4);
   IoPortAddr[DUCRA] = (0x5 << 4);

   /* reset error status */
   IoPortAddr[DUCRA] = (0x4 << 4);

   /* set for no N81, normal operation */
   IoPortAddr[DUCRA] = (0x1 << 4);
   IoPortAddr[DUMRA] = 0x13;
   IoPortAddr[DUMRA] = 0x7;

   /* set port speed-- 9600 bps */
   IoPortAddr[DUCRA] = (0x1 << 4);
   IoPortAddr[DUACR] = (DUacr |= 0x80);
   IoPortAddr[DUCSRA] = 0xbb;

   /* init counter- counter mode, external clock source */
   IoPortAddr[DUACR] = (DUacr |= 0x30);

This is not the complete function, but you can see that it writes values
to the same location more than once, without ever accessing values from
that location. This tells the compiler that all assignments except the
last one (to a given location) are meaningless and can be discarded. I
have verified this by examining the assembler listing generated by GCC.

Any suggestions? I've gotta think someone else has run into this before.

Thanks for any help!

More information about the crossgcc mailing list