搜索
bottom↓
回复: 15

avrgcc优化:使用全局性优化参数

[复制链接]

出0入0汤圆

发表于 2008-3-27 13:34:44 | 显示全部楼层 |阅读模式
这个优化方法必须对makefile作修改,无法直接在avr studio中设置,所以新手慎用。
这几天avrfreaks上有个优化的讨论贴(我也顺便插了一脚^_^),EW大大推荐了一对优化参数

-combine -fwhole-program

(这位EW大大就是winavr的工程管理者Eric Weddington,sf上的用户名是arcanum,
在avrfreaks上比较活跃的。顺便插播个新闻,他在某个帖子中说,他在这2个月内[最快这几天]打算发布新版的winavr,
增加对xmega的ATxmega128A1,ATxmega64A1,及ATmega32C1, ATmega32M1, ATmega32U4,ATtiny167等新mcu的支持,
当然也包括了gcc 4.3.0)

适用版本为winavr 20071221,
注意,20070525使用该参数是有bug的,会导致中断向量表无法和代码里的中断函数地址关联起来(向量表会全为默认地址)

先来看下我手头一个工程优化的效果对比(128的):
-0s avrstudio的自动生成的makefile编译结果
Program:   40508 bytes (30.9% Full)
(.text + .data + .bootloader)

Data:       2519 bytes (61.5% Full)
(.data + .bss + .noinit)

然后是-combine -fwhole-program
Program:   35694 bytes (27.2% Full)
(.text + .data + .bootloader)

Data:       2160 bytes (52.7% Full)
(.data + .bss + .noinit)

代码部分相差约4%,数据部分差约9%!
连data和bss段都被优化了?!

不过优化后的代码我还没有用实物实测过(手头暂时没有板子)

以下是这2个参数的解释(来自gcc 4.1.2文档):
-combine :
If you are compiling multiple source files, this option tells the driver to pass
all the source files to the compiler at once (for those languages for which the
compiler can handle this). This will allow intermodule analysis (IMA) to be
performed by the compiler. Currently the only language for which this is supported
is C. If you pass source files for multiple languages to the driver, using
this option, the driver will invoke the compiler(s) that support IMA once each,
passing each compiler all the source files appropriate for it. For those languages
that do not support IMA this option will be ignored, and the compiler will be
invoked once for each source file in that language. If you use this option in conjunction
with ‘-save-temps’, the compiler will generate multiple pre-processed
files (one for each source file), but only one (combined) ‘.o’ or ‘.s’ file.

-fwhole-program :
Assume that the current compilation unit represents whole program being compiled.
All public functions and variables with the exception of main and those
merged by attribute externally_visible become static functions and in a affect
gets more aggressively optimized by interprocedural optimizers. While this
option is equivalent to proper use of static keyword for programs consisting
of single file, in combination with option ‘--combine’ this flag can be used to
compile most of smaller scale C programs since the functions and variables become
local for the whole combined compilation unit, not for the single source
file itself.

简单的说,-combine会把所有指定的源代码文件一起传递给gcc(就类似把代码都写在一个c文件里),使得-fwhole-program能让gcc使用“模块互调分析”(IMA)
(目前该分析功能只支持c语言,另外这个词的中文译文是我自己翻的^_^),对同一类语言的代码所有文件作为整体来分析其结构。
而-fwhole-program则会把除了main和externally_visible属性定义的变量或函数外的所有公共函数、变量做静态处理,成为内部的变量、函数。

要注意的事项:
1. -fwhole-program会导致目标文件中所有没有用externally_visible属性定义的变量或函数对外部不可见,所以库的编译一般不用这个参数
2. -fwhole-program应当是对整个工程代码为目标的做优化的,而不是单个源代码文件(那就完全失去全局性优化的意义,而且会因为上面说的不可见性,导致其它文件中无法调用该文件里的函数或变量)
3. 在极少数情况下,它可能会反而增加编译后的大小。
4. 要注意不能用20070525版编译。
5. 建议在一般-0s优化编译完成,并确认程序运行正常后,再使用该参数重新编译测试,不要在开发中就使用(因为使用了后,map文件里就看不到变量的地址分配了)。

设置方法:

这里我以avrstudio自动生成的makefile为基础来修改,

先找到OBJECTS的设置,比如我这里是这样的:
## Objects that must be built in order to link
OBJECTS = exmem.o func.o init.o main.o timer.o twi_master_drv.o uart.o
等号后面的全部删除(我不需要编译出obj文件,只需要直接产生elf),变成这样:
## Objects that must be built in order to link
OBJECTS =

然后找到## Compile,可以看到一长排这样的语句(每个c文件对应一个)
## Compile
main.o: ../src/main.c
        $(CC) $(INCLUDES) $(CFLAGS) -c  $<
...

##Link

把## Compile和##Link之间的全部删除,

再修改TARGET的规则:
##Link
$(TARGET): $(OBJECTS)
         $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
改为
##Link
$(TARGET):
         $(CC) $(INCLUDES) $(CFLAGS) $(wildcard ../src/*.c) $(LDFLAGS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
我的c文件都在"../src/"这个目录下的,所以直接用wildcard函数。$(CFLAGS)里不要用-c参数。

最后,加入这2个参数:
CFLAGS += -combine -fwhole-program

OK,另存,接下来只要在avrstudio里选择使用这个外部makefile,rebuild all,就行了(别忘记测试下,我还没运行测试过(-_-;)。
至于倒底gcc如何在-0s基础上再优化的,有兴趣的网友可以去研究研究(我目前没空去比较了^_^)

其它优化参数还可以看一下我以前的帖子:
不链接未调用函数和用rjmp替换jmp实现方法
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=838274

另外,20070525如果要使用这对参数,需要使用自己根据中断函数改写的start file(比如改写avr-libc的gcrt1.S)来链接,而不能用gcc默认的启动代码。

出0入0汤圆

发表于 2008-3-27 14:09:23 | 显示全部楼层
学习了。

出0入0汤圆

发表于 2008-6-4 00:04:09 | 显示全部楼层
记号
头像被屏蔽

出0入0汤圆

发表于 2008-6-4 00:39:17 | 显示全部楼层
学习。

出0入0汤圆

发表于 2008-6-4 21:56:01 | 显示全部楼层
类似IAR的优化方式

不过我用GCC主要是看中它的全项目联调能力,能够用一个makefile和一组头文件作出8位MCU、32位终端、PC上位的全部运行代码,这样一来,这种优化方法就很难用上了……虽然不是不能,但太过麻烦了……

出0入0汤圆

发表于 2008-6-4 22:09:11 | 显示全部楼层
watercat,我觉得应该不成问题,因为c编译器是不同的,对不同的目标处理器肯定是有不同的编译参数设置的。

出0入0汤圆

发表于 2008-6-4 22:58:15 | 显示全部楼层
学习

出0入0汤圆

发表于 2008-6-4 23:16:11 | 显示全部楼层
【5楼】 gingin
        watercat,我觉得应该不成问题,因为c编译器是不同的,对不同的目标处理器肯定是有不同的编译参数设置的。
====================
那需要为每一个环境单独配置编译,并且难以控制源文件的裁剪组合

更重要的是,至少对我所做的项目来说,tiny24/mega48放不下的代码,换tiny44/mega88就是了,价格贵不了两块钱,却没必要为了几十个字节的优化而引入可能的不稳定,毕竟代码中的很多对稳定性有所助益的措施,在编译器看来那就是多余的……

出0入0汤圆

发表于 2008-6-4 23:21:50 | 显示全部楼层
学习,就是有点麻烦

出0入0汤圆

发表于 2009-6-21 11:40:47 | 显示全部楼层
顶下

出0入0汤圆

发表于 2009-6-21 19:44:56 | 显示全部楼层
学习

出0入0汤圆

发表于 2009-6-21 20:27:20 | 显示全部楼层
原创的就是最好的,LZ真棒

出0入0汤圆

发表于 2009-6-22 17:42:10 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-7-20 15:44:55 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-11-16 19:10:15 | 显示全部楼层
学习

出0入0汤圆

发表于 2010-12-19 19:31:54 | 显示全部楼层
mark一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 17:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表