- 1、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
alterastratixiii器件助力业界容量最大的asic原型电路板
针对嵌入式SoC应用的C编程优化 开发运行在SoC内的嵌入式处理器内核的程序时,工程师有两个主要目的:运行得足够快,使处理器运行的频率降到最低;消耗尽量少的内存,使内存开销降到最小。 对于不同的项目,有时候这两个因素的重要性会不一样。下面两个关键因素极大地影响着设计团队满足这些目标的能力:开发源程序的编译器对代码的优化效率以及用于开发源代码的编程风格。本文将深入地讨论这两种因素,并提出一些创建小而快的C程序的建议。 编译器原理 编译器通常是由前端和后端两部分组成。前端通常是指语法和语义的处理过程,后端通常是指优化、代码生成,以及针对特定处理器的优化过程。很多好的编译器后端依赖于多层的中间表述(IR)。优化和代码生成从高层(类型输入程序的句法)到低层逐级地传递中间表述。与处理器无关的优化一般倾向于在编译过程的早期在较高IR层上实现,而针对特定处理器的优化一般倾向于在编译过程的后期在低层IR上来实现。信息通过不同IR层向下传递,这样低层优化可以充分利用编译器早期处理得到的高层信息。 Tensilica针对其Xtensa可配置处理器和Diamond标准处理器的XCC/C++编译器包含四个基本的优化级,从-O0到-O3,对应着不断提高的优化级别。表1描述了这些级别及其相对应的代码大小和内部过程分析(IPA)。缺省情况下,XCC编译器一次优化一个文件,但是它也可以执行内部过程分析(通过加入IPA的编译选项)。当在多个原文件上优化整个应用程序时,优化将会被延迟到链接的步骤之后进行。表2描述了当前编译器(包括XCC编译器)支持的优化内容部分列表。 XCC编译器还可以利用编译产生的性能分析数据。性能分析的反馈可以帮助编译器减轻分支跳转的延迟。另外,反馈可以让编译器只是插入那些最常用的函数(inline),并且妥善处理常用代码段中寄存器溢出的问题。因此,性能分析反馈允许XCC编译器在所有地方进行正常优化的同时,还可以通过优化应用中的临界部分进行加速。 一些有用的C编码规则 为了利用编译器得到最好的性能,编程人员需要像编译器一样思考问题,并且理解C语言和目标处理器之间的关系。下面的一些基本原则可以帮助所有嵌入式编程人员在不需很大努力的情况下获得性能好很多的编译代码。 1. 观察编译得到的代码 完全理解编译器对全部代码如何编译是不可能的。如果XCC编译器设置了—S或者-save-temps编译选项,编译将产生汇编输出并且还有一些为了理解而添加的注释。对于那些性能要求很高的代码,你可以观察编译结果是否符合你的期望。如果不是,请考虑以下规则。 2. 了解混淆发生的情况 C语言允许任意地使用指针,这增加了混淆出现的机会,这允许程序用很多种方法去引用同一数据对象。如果全局变量的地址被作为子程序的参数传递,这个变量可以通过它的名字或者通过指针被引用。这就是一种混淆,编译器必须保守地把这样的数据对象保存在内存中而不是寄存器中,并且仔细地保持代码中可能引起混淆的变量的访问顺序。考虑下面的代码: void foo(int *a, int *b) { int i; for (i=0; i100; i++) { *a += b[i]; } } 您会设想编译器应该产生代码是在循环开始前将*a保存到一个寄存器里面,并且在循环中把b[i]保存到一个寄存器里面然后将它加到*a所在的寄存器里。但事实上却是,编译器产生的结果是*a被放置在内存里面,因为a和b可以产生混淆情况,*a也许是b数组的一个元素。虽然看起来在这个例子中不太可能出现这种混淆,但是编译器是没法确定这种情况是否会发生的。有几个技巧可以针对混淆的情况,帮助编译器能做到更好的编译工作:你可以使用-IPA编译选项进行编译,你可以用全局变量代替参数,你可以使用特殊编译选项进行编译,或者可以在声明变量中使用_restrict属性。 3. 指针常常引起混淆 编译器识别指针指向的目标对象经常会遇到问题。程序员可以通过使用本地变量帮助编译器去避免混淆,具体方法是使用本地变量去存储依据指针访问获得的值,因为不直接的操作和调用影响指针引用的值而不是本地变量的值。因此,编译器会把本地变量放到寄存器里面去。 下面的例子显示如何正确使用指针以避免混淆从而产生更好的编译代码。在这个例子里面,优化者不知道*p++=0是否会修改len,所以它不能把len放到寄存器里面去获得性能提升。相反每个循环中,len都被放到了内存里面。 int len = 10; void zero(char *p) { int i; for (i=0; i } 通过使用本地变量而不是全局变量,可以避免混淆。 int len = 10; void zero(char *p) { int local_len
文档评论(0)