Application size & Optimization Warnings?

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings -

 

I have a M328P program that occupies 32720 bytes (as reported on the build output) with no bootloader and BOOTRST = false. RAM is it 65% and EEPROM is at 5%. Other than the fact that there are only a few bytes remaining in flash, are there any inherent problems with running this close to absolute-full?

 

A related question. I just discovered that, sometime in the past, I had set optimization level at -O1 (byte count above). When I change to -Os, the usage drops to 29224 bytes (nice) but I get a slew of warnings:

 

Severity

Code

Description

Project

File

Line

Warning

 

dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

ALoggerF2

C:\Users\Jim\Dropbox\Accelerometer Docs\Code\ALoggerF2-ADC\ALoggerF2\ALoggerF2\ff.c

798

 

A typical line that generates this warning is:

 

ST_DWORD(fs->win+FSI_LeadSig, 0x41615252);

 

These are all from relatively old version fatfs library files and are absent with -O1. What are the issues of ignoring this?

 

Thanks

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Tue. Feb 6, 2018 - 05:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
Other than the fact that there are only a few bytes remaining in flash, are there any inherent problems with running this close to absolute-full?
No - the only one of concern would be the RAM but 65% should be "safe". The only concern there would be if you were making huge use of automatics but 35% of 2K is 716 bytes so you'd have to be going some to eat all that using the stack!

 

As to the warning. "type punning" is when pointers to one data type are "massaged" to be used to point to data of another type. As the code is presumably already proven to be "safe" then I think you can consider the warnings benign. In fact you might want to follow the advice in the warning. The bit that says "[-Wstrict-aliasing]" is saying that it's because that option is enabled to the compiler that you see the warning. So if you want to quell them use "-Wnostrict-aliasing" (you can generally add "no" to the start of all these to disable them.

 

BTW looking at the code that throws that warning:

static
FRESULT sync_fs (	/* Returns FR_OK or FR_DISK_ERR */
	FATFS* fs		/* Filesystem object */
)
{
	FRESULT res;


	res = sync_window(fs);
	if (res == FR_OK) {
		if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) {	/* FAT32: Update FSInfo sector if needed */
			/* Create FSInfo structure */
			mem_set(fs->win, 0, SS(fs));
			st_word(fs->win + BS_55AA, 0xAA55);
			st_dword(fs->win + FSI_LeadSig, 0x41615252);
			st_dword(fs->win + FSI_StrucSig, 0x61417272);

The parameter passed to this function is "FATFS *" which is a struct pointer. It points to structs of this type:

/* Filesystem object structure (FATFS) */

typedef struct {
	BYTE	fs_type;		/* Filesystem type (0:N/A) */
	BYTE	pdrv;			/* Physical drive number */
	BYTE	n_fats;			/* Number of FATs (1 or 2) */
	BYTE	wflag;			/* win[] flag (b0:dirty) */
	BYTE	fsi_flag;		/* FSINFO flags (b7:disabled, b0:dirty) */
	WORD	id;				/* Volume mount ID */
	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
	WORD	csize;			/* Cluster size [sectors] */

[snip]

	DWORD	volbase;		/* Volume base sector */
	DWORD	fatbase;		/* FAT base sector */
	DWORD	dirbase;		/* Root directory base sector/cluster */
	DWORD	database;		/* Data base sector */
	DWORD	winsect;		/* Current sector appearing in the win[] */
	BYTE	win[FF_MAX_SS];	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
} FATFS;

So "win" within this is an array of BYTE but it's an array of BYTE within a FATFS struct. That is passed as the first parameter in a call to:

			st_dword(fs->win + FSI_LeadSig, 0x41615252);

and that function has the interface:

static
void st_dword (BYTE* ptr, DWORD val)	/* Store a 4-byte word in little-endian */
{

which is a plain pointer to BYTE. Although ultimately "fs->win + n" and "BYTE *ptr" both point to BYTEs they are slightly different pointers and that is why it's complaining. Another approach is to modify the code to cast:

			st_dword((BYTE *)(fs->win + FSI_LeadSig), 0x41615252);

though that would be cumbersome.

 

I must say that I am a bit surprised that the appearance of the warning is switched by changing -O1 to -Os. Not sure why the latter would introduce -Wstrict-alias. The user manual tells us that -Os is effectively -O2 minus:

 

-falign-functions  -falign-jumps  -falign-loops 
-falign-labels  -freorder-blocks  -freorder-blocks-algorithm=stc 
-freorder-blocks-and-partition  -fprefetch-loop-arrays

It also says that -O2 is -O1 plus:

 

-fthread-jumps 
-falign-functions  -falign-jumps 
-falign-loops  -falign-labels 
-fcaller-saves 
-fcrossjumping 
-fcse-follow-jumps  -fcse-skip-blocks 
-fdelete-null-pointer-checks 
-fdevirtualize -fdevirtualize-speculatively 
-fexpensive-optimizations 
-fgcse  -fgcse-lm  
-fhoist-adjacent-loads 
-finline-small-functions 
-findirect-inlining 
-fipa-cp 
-fipa-bit-cp 
-fipa-vrp 
-fipa-sra 
-fipa-icf 
-fisolate-erroneous-paths-dereference 
-flra-remat 
-foptimize-sibling-calls 
-foptimize-strlen 
-fpartial-inlining 
-fpeephole2 
-freorder-blocks-algorithm=stc 
-freorder-blocks-and-partition -freorder-functions 
-frerun-cse-after-loop  
-fsched-interblock  -fsched-spec 
-fschedule-insns  -fschedule-insns2 
-fstore-merging 
-fstrict-aliasing 
-ftree-builtin-call-dce 
-ftree-switch-conversion -ftree-tail-merge 
-fcode-hoisting 
-ftree-pre 
-ftree-vrp 
-fipa-ra

but I don't see what this has to do with warnings about pointer aliasing?

 

Are you sure that when you made the switch from -O1 to -Os you didn't also enable something like -Wall at the same time?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Those warnings may matter. And it's completely normal not to see them at -O1.

 

When you increase optimization levels, you increase the number of optimizations used. Some things are not capable of being problems unless you are using more optimizations.

 

 

Note the presence of "-fstrict-aliasing" in the big list. What's that do, exactly?

 

the gcc man page says:

           Allow the compiler to assume the strictest aliasing rules applicable to the language being
           compiled.  For C (and C++), this activates optimizations based on the type of expressions.  In
           particular, an object of one type is assumed never to reside at the same address as an object of a
           different type, unless the types are almost the same.  For example, an "unsigned int" can alias an
           "int", but not a "void*" or a "double".  A character type may alias any other type.

 

So, let's do an example.

union foo {
    int a;
    double d;
}

int x(void) {
    union foo u;
    u.a = 1;
    u.d = 2.0;
    return u.a;
}

With -fstrict-aliasing, the compiler knows that the modification to u.d cannot possibly have modified the value of u.a. It can determine that nothing refers to u.d, and drop the "dead" assignment, and just return the value assigned to u.a immediately. This is an optimization -- less code is generated!

 

 

 

But it turns out it changes behavior. It's just that the behavior was undefined, so from the compiler's standpoint, this isn't changing the behavior of correct code, and you did say you wanted smaller code.

 

The manual states that -Wstrict-aliasing only shows up when -fstrict-aliasing is on.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Normally I use: -Os -fno-jump-tables -flto (-fno-jump-tables may or may not reduce code size)

Option -flto sometimes breaks stuff, but -Os, I never noticed it to generate new warnings.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Absolutely nothing was changed other than the optimization flag, -O1 to -Os. All other flags are as default.

 

I suspect that the original change to O1 may have been due to the warnings or, it might just have been due to debugging. Or, maybe both, that is now lost in the fog of time.

 

I am really uncomfortable trying to fix these warnings. The FatFs code has, otherwise, been impeccable and it works. Plus, I do not understand big chunks of it. 

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The real seesb has explained that after study of the user manual. It's a consequence of -fstrict-alias

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, so here's a suggestion.

 

Try compiling with the same options, plus -fno-strict-alias. I think that'll turn it off and suppress the warnings.

 

But wait! Here's the fun part: See whether the generated code changes. If it changes, then I would strongly recommend that you either study the code until you can correct the issue, or keep -fno-strict-alias in place. It is absolutely possible the code is doing something which is actually undefined behavior, and gcc will absolutely do crazy stuff when optimizing that can break such code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm rereading this more carefully. Does the cast you describe actually have any effect? It certainly shouldn't.

 

I've gone and looked at the current version of fatfs code, and I can't reproduce this behavior: I can compile with any optimizations I want and not see this. It's possible that the "older" version you have has subtly different code, but the specific code you're getting the warning from looks the same to me. I've tried x86 gcc, I've tried avr-gcc. What's the full command line exactly?

 

(Spot the guy who used to do toolchain maintenance.)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Same result here:

D:\ffsamp_oct2017\avr>make -f Makefile_mmc
The system cannot find the path specified.
ECHO is off.
xitoa.S :
avr-gcc -c -mmcu=atmega1284p -I. -x assembler-with-cpp  -Wa,-gstabs,-gdwarf-2 xitoa.S -o obj_mmc/xitoa.o
ECHO is off.
main.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/main.o,-MF,
obj_mmc/main.d main.c -o obj_mmc/main.o
ECHO is off.
uart.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/uart.o,-MF,
obj_mmc/uart.d uart.c -o obj_mmc/uart.o
ECHO is off.
diskio.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/diskio.o,-M
F,obj_mmc/diskio.d diskio.c -o obj_mmc/diskio.o
ECHO is off.
mmc_avr_usart.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/mmc_avr_usa
rt.o,-MF,obj_mmc/mmc_avr_usart.d mmc_avr_usart.c -o obj_mmc/mmc_avr_usart.o
ECHO is off.
rtc_ds1338.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/rtc_ds1338.
o,-MF,obj_mmc/rtc_ds1338.d rtc_ds1338.c -o obj_mmc/rtc_ds1338.o
ECHO is off.
ff.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/ff.o,-MF,ob
j_mmc/ff.d ff.c -o obj_mmc/ff.o
ECHO is off.
ffunicode_avr.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/ffunicode_a
vr.o,-MF,obj_mmc/ffunicode_avr.d ffunicode_avr.c -o obj_mmc/ffunicode_avr.o
ECHO is off.
sound.c :
avr-gcc -c -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/sound.o,-MF
,obj_mmc/sound.d sound.c -o obj_mmc/sound.o
ECHO is off.
Linking...
avr-gcc -std=gnu89 -gdwarf-2 -mmcu=atmega1284p -Os -mcall-prologues -Wall -Wextra  -DF_CPU=20000000 -DDRV_MMC=0 -Wp,-MM,-MP,-MT,obj_mmc/avr_mmc.o,-MF,
obj_mmc/avr_mmc.d -Wl,-Map,obj_mmc/avr_mmc.map obj_mmc/xitoa.o obj_mmc/main.o obj_mmc/uart.o obj_mmc/diskio.o obj_mmc/mmc_avr_usart.o obj_mmc/rtc_ds13
38.o obj_mmc/ff.o obj_mmc/ffunicode_avr.o obj_mmc/sound.o -o obj_mmc/avr_mmc.elf
ECHO is off.
avr-objcopy -j .text -j .data -j .eeprom -j .fuse -O ihex obj_mmc/avr_mmc.elf obj_mmc/avr_mmc.hex
ECHO is off.
avr-objdump -h -S -C obj_mmc/avr_mmc.elf > obj_mmc/avr_mmc.lst
ECHO is off.
avr-nm -n obj_mmc/avr_mmc.elf > obj_mmc/avr_mmc.sym
ECHO is off.
avr-size obj_mmc/avr_mmc.elf
   text    data     bss     dec     hex filename
  68706     157    7013   75876   12864 obj_mmc/avr_mmc.elf

That is using -Os and even thought the Makefile specifies "-Wall -Wextra" I'm not getting the warning. I'm using a 5.3 on Windows.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the reasons why I stuck with -O1 was the fear that the compiled code does change. Until now,  size was not a concern. 

 

I have not updated the FatFs version from R 0.0.9b I use because, even with Cliff's very helpful example, I had a major difficulty getting it going, though I still don't understand why. And, because I have heard tales of bloat in recent versions. 

 

Using AS 7.0.634 over concerns about changing tool chain mid-project. 

 

Since  I am still within the FLASH boundaries and since this is a custom version for one customer, I think that I'll stay with the -O1. The fit will hit the shan on the next major revision. If you can't  fix it, hide it, right?

 

Jim

 

 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, this is *really* interesting: I can't reproduce this with that version, either! I don't have AS, though, just avr-gcc etcetera.

 

And the thing is, the code looks right to me. It doesn't violate strict aliasing rules at all, it's correct. Would be super interested in the exact command line or whatever being used, since that message is definitely a gcc-ism, so it's *some* version of gcc being used.

 

I'd say either stick with -O1, or try -Os -fno-strict-aliasing. Good luck.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How do you get the command line that AS uses? I don't know!

 

I see "avr8-gnu-toolchain-3.5.0.1662-readme" in the atmel directory chain. But, when I do a build, I see "invoking: AVR/GNU C Compiler : 4.9.2". Maybe this is the command line:

    Invoking: AVR/GNU C Compiler : 4.9.2

        "C:\Program Files (x86)\Atmel\Studio\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-gcc.exe"  -x c -funsigned-char -funsigned-bitfields -DDEBUG  -I"C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.90\include"  -Os -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.90\gcc\dev\atmega328p" -c -std=gnu99 -MD -MP -MF "accel.d" -MT"accel.d" -MT"accel.o"   -o "accel.o" ".././accel.c" 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Wed. Feb 7, 2018 - 07:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That looks like it. And inexplicably, I still don't get that warning, so now I'm really curious as to how on earth this could happen.