精华内容
下载资源
问答
  • 编译器优化
    2022-01-17 10:28:36

    详解C/C++中volatile关键字

    C语言关键字volatile

    C语言关键字volatile(注意它是用来修饰变量而不是上面介绍的volatile)表明某个变量的值可能在外部被改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新存取。该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程,

    也就是说,线程一和线程二使用同一个变量、
    但是由于编译器优化,导致线程一更改该变量后,将其缓存在寄存器中,还没来得及其更新到内存中,线程二使用到该变量时,从内存中读取该变量,就无法获取到该变量的真实值。

    为什么要做这种优化?
    因为cpu从寄存器中读写数据远快于cpu从内存中读写数据,
    线程一使用完该变量后,就将其存放在了寄存器,然而线程二并不知道线程一把该变量放在了寄存器中,还傻傻的从内存中读取该变量,肯定读不到正确的值(即更新后的值)

    volatile的本意是“易变的”,由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化
    https://blog.csdn.net/weixin_44363885/article/details/92838607?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164238237016780261926922%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164238237016780261926922&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-3-92838607.first_rank_v2_pc_rank_v29&utm_term=volatile%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E4%BD%9C%E7%94%A8+c&spm=1018.2226.3001.4187

    更多相关内容
  • 今天别人分析一个问题,觉得挺有意思,拿出来分享一下。
  • 编译器中的优化编译器优化选项优化指令 编译器优化选项 所有C++编译器有各种你可以打开、关闭的优化选项。学习正在使用编译器可用的选项,并打开所有相关选项,是重要的。 许多优化选项与调试不兼容。调试器可以一次...

    编译器优化选项

    所有C++编译器有各种你可以打开、关闭的优化选项。了解正在使用编译器可用的选项,并打开所有相关选项,是重要的。

    许多优化选项与调试不兼容。调试器可以一次执行一行代码,并显示所有变量的值。显然,在部分代码被重排、内联或优化掉时,这是不可能的。通常制作可执行程序的两个版本:带有完整调试支持,在程序开发期间使用的调试版本;以及打开所有相关优化选项的发布版本。大多数IDE(集成开发环境)有制作目标文件与可执行文件的调试版本与发布版本的设施。确保区分这两个版本,在可执行文件的优化版本里关闭调试与分析支持。

    大多数编译器提供优化大小与优化速度的选择。优化大小:在代码是快速的且希望可执行文件尽可能小,或者代码缓存是关键的时。优化速度:在CPU使用与内存使用是关键时间消耗者时。最高的优化等级选项通常是最好的,除了一些特定的场景。

    某些编译器提供分析指引(profile-guided)优化。这以下面的方式工作。首先,你使用分析支持编译程序。然后,你使用分析器进行一次测试运行,确定程序流以及每个函数与分支执行的次数。然后,编译器可以使用这个信息优化代码,以最优的次序放置不同的函数。

    某些编译器支持全程序优化。这通过两步编译进行。首先,所有的源文件被编译为一个中间文件格式,而不是普通的目标文件格式。然后第二步,中间文件被链接起来。寄存器分配与函数内联在第二步完成。中间文件格式不是标准化。甚至在同一个编译器的不同版本间也不兼容。因此,以这个格式发布函数是不可能的。

    其他编译器提供了将多个.cpp文件编译为单个目标文件的可能性。进行全程序优化一个更原始、但高效的方式是,通过#include指示把所有的源文件合并为一个,并把所有函数声明为staticinline。这将使编译器能进行全程序的过程间优化。

    在不需要与旧CPU兼容时,你可以选择较新的指令集。甚至更好,你可以制作代码关键部分的多个版本以支持不同的CPU。

    在没有异常处理时,代码变得更高效。建议关闭异常处理的支持,除非代码依赖结构化的异常处理,且你希望代码能够从异常恢复。

    建议关闭运行时类型识别(RTTI)的支持。

    建议启用快速浮点计算或者关闭严格浮点计算,除非需要严格检查。

    如果可能,打开“函数级内联”选项。

    如果你确定代码没有指针别名,使用“假定没有指针别名”选项。参考第66页解释。

    许多编译器有用于“标准栈框”或“框指针”的选项。标准栈框用于调试与异常处理。忽略标准栈框使函数调用更快,使得一个寄存器用可于其他目的。这是一个优势,因为寄存器是一种稀缺资源。不要使用栈框,除非你的程序依赖异常处理。

    优化指令

    某些编译器有许多关键字与指令用于在代码特定位置给出特定的优化指令。许多这些指示是与编译器相关的。你不能预期用于Windows编译器的指令能在Linux编译器上工作,反之亦然。但大多数Microsoft指令在用于Windows的Intel编译器与Gnu编译器上起作用,而大多数Gnu指令在用于Linux的PathScale与Intel编译器上起作用。

    在所有C++编译器上起作用的关键字

    关键字volatile确保一个变量不会被保存在寄存器里,即使临时。这目的在于在多个线程间共享变量,但它也可以用于关闭用于测试目的变量的所有优化。

    关键字const告知变量永远不会改变。这在许多情形里允许编译器优化掉变量。例子:

    // Example 8.24. Integer constant
    const int ArraySize = 1000;
    int List[ArraySize];
    ...
    for (int i = 0; i < ArraySize; i++) List[i]++;
    

    这里,编译器可以使用值1000替换所有出现的ArraySize。在例子8.24中的循环可以更高效的方式实现,如果循环计数器(ArraySize)的值是常量,且在编译时刻已知。整数常量不分配内存,除非它的地址被计算(&ArraySize)。

    const指针或const引用不能改变所指向对象。const成员函数不能修改数据成员。建议只要合适,使用const关键字向编译器给出关于变量、指针或成员函数的额外信息,因为这会提高优化的可能性。例如,编译器可以安全地假设类数据成员的值在调用const成员函数期间不会改变。

    关键字static有几个含义,依赖于上下文。关键字static,在应用到非成员函数时,表示不会从其他模块访问该函数。这使得内联更高效,并启用过程间优化。
    关键字static,在应用到全局变量时,表示不会从其他模块访问它。这会启用过程间优化。
    关键字static,在应用到函数内局部变量时,表示在该函数返回时这个变量将被保留,并在该函数下一次被调用前维持不变。这可能是效率低的,因为某些编译器将插入额外的代码,防止从多个线程同时访问该变量。即使变量是常量,这也适用。
    将局部变量声明为staticconst,确保它仅在函数第一次被调用时被初始化也是有原因的。例子:

    // Example 8.25
    void Func () {
         static const double log2 = log(2.0);
         ...
    }
    

    这里,仅在Func第一次执行时,才计算log(2.0)。没有static,每次执行Func时,将重新计算这个对数。坏处是函数必须检查它是否已经被调用过。使log2成为一个全局const变量或者以计算值替换它,会更快。
    关键字static,在应用到类成员函数时,表示它不能访问任何非静态数据成员或成员函数。静态成员函数的调用比非静态成员函数快,因为它不需要this指针。建议只要合适,将成员函数声明为static

    编译器特定关键字

    快速函数调用。__fastcall或者__attribute__((fastcall))。在32位模式中,fastcall修饰符会使32-bit模式函数调用更快。前两个整形参数在寄存器中传递而不是栈。Fastcall函数在编译器间不兼容。在参数在寄存器中传递的64位模式中,不需要fastcall。

    纯函数。__attribute__((const))(仅Linux)。声明一个函数为纯函数。这允许公共子表达式消除与循环不变代码移动。

    假设没有指针别名。__declspec(noalias)__restrict#pragma optimize(“a”, on)。说明指针别名不会发生。注意这些指示不总是能工作。

    数据对齐。__desclspec(align(16))__attribute__((aligned(16))。C++11中,被alignas(16)指定数组或结构体的对齐。对向量操作有用。

    展开全文
  • 而在本文中,将涉及c编译器的高级部分——c编译器及其优化。所以,本文的讲解需要大家具备一定的c编译器基础,以及一定的c语言代码编写能力。此外,本文的内容的开发环境基于ARM处理器,相关技术同样可在RISC处理器...

    对于c编译器,想必大家也有所了解,3款主流c编译器也是活跃在不同人群的PC上。网络上很多文章都止步于对c编译器的介绍,并未探索c编译器更加深层次的内容。而在本文中,将涉及c编译器的高级部分——c编译器及其优化。所以,本文的讲解需要大家具备一定的c编译器基础,以及一定的c语言代码编写能力。

    此外,本文的内容的开发环境基于ARM处理器,相关技术同样可在RISC处理器上实现,所以同样需要读者具备最基础的处理器知识。

    70a7EGHMh9fnF6yRE5g%2BQJiVhdJn%2FB%2F%2BdU2EU1bNsSpMhoqy4qXz8Vm9eyJE8f4nkNwdGsZIqy5%2FXTX%2BJOnLAfsmBBUVldp7y9cEQLSCQGwnGhCKKBTJmvH9vcGKOA

    本文主要讲解C编译器在代码优化时遇到的一些问题。要编写高效的C语言源代码,必须了解C编译器对什么形式的代码有所改动,编译器涉及的处理器结构的限制,以及一些特殊的C编译器的限制。

    1.为编译器选择处理器结构

    在编译C源文件时,必须为编译器指定正确的处理器类型。这样可以使编译的代码最大限度地利用处理器的硬件结构,如对半字加载(Halfword Load)、存储指令(Store InstrucTIons)和指令调度(InstrucTIon Scheduling)的支持。所以编译程序时,应该尽量准确地告诉编译器该代码是运行在什么类型的处理器上。有些处理器类型编译器是不能直接支持,如SA-1100,这时可以使用与该类型处理器为同一指令集的基本处理器,比如对于SA-100,可以使用StrongARM。

    注意指定目标处理器可能使代码与其他ARM处理器不兼容。例如,编译时指定了ARMv6体系结构的代码,可能不能运行在ARM920T的处理器上(如果代码中使用了ARMv6体系结构中特有的指令)。

    选择处理器类型可以使用--cpu name编译选项。该选项生成用于特定ARM处理器或体系结构的代码。

    如果name是处理器名称。

    · 输入名称必须和ARM数据表中所示严格一致,例如ARM7TDMI。该选项不接受通配符字符。有效值是任何 ARM6 或更高版本的 ARM 处理器。

    · 选择处理器操作会选择适当的体系结构、浮点单元 (FPU)以及存储结构。

    · 某些--cpu选择暗含--fpu选择。例如,当使用--arm选项编译时,--cpu ARM1136JF-S暗含--fpu vfpv2。隐式FPU只覆盖命令行上出现在--cpu选项前面的显式--fpu选项。如果没有指定--fpu选项和--cpu选项,则使用--fpu softvfp。

    2.调试选项

    如果在编译C源程序时,设置了调试选项,这将很大程度地影响最终代码的大小和执行效率。因为带调试信息的代码映像,为了能够在调试程序时正确地显示变量或设置断点,包含很多冗余的代码和数据。所以如果想最大限度地提供程序执行效率、减少代码尺寸,就要在编译源文件时,去除编译器的调试选项。

    以下选项指定调试表生成方法。

    · -g (--debug):该选项启用生成当前编译的调试表。无论是否使用-g选项,编译器都生成的代码是相同的。惟一差别是调试表的存在与否。编译器是否对代码进行优化是由-O选项指定调的。默认情况下,使用-g选项等价于使用:-g -dwarf2 --debug_macros。

    注意编译程序时,只使用-g选项而没有使用优化选项,编译器会提示警告信息。

    · --no_debug:该选项禁止生成当前编译的调试表。这是默认选项。

    · --no_debug_macros:当与-g一起使用时,该选项禁止生成预处理程序宏定义的调试表条目(Entry)。这会减小调试映像的大小。-gt-p是-gtp的同义字。

    --debug_macros 当与 -g 一起使用时,该选项启用生成预处理程序宏定义的调试表条目。这是默认选项,会增加调试映像的大小。一些调试程序忽略预处理程序条目。

    3.优化选项

    使用-Onum选择编译器的优化级别。优化级别分别为。

    · -O0:除一些简单的代码编号之外,关闭所有优化。使用该编译选项可以提供最直接的优化信息。

    · -O1:关闭严重影响调试效果的优化功能。使用该编译选项,编译器会移除程序中未使用到的内联函数和静态函数。如果与 --debug 一起使用,该选项可以在较好的代码密度下,给出最佳调试视图。

    · -O2:生成充分优化代码。如果与 --debug 一起使用,调试效果可能不令人满意,因为目标代码到源代码的映射可能因为代码优化而发生变化。

    如果不生成调试表,这是默认优化级别。

    · -O3:最高优化级别。使用该优化级别,使生成的代码在时间和空间上寻求平衡。该选项常和-Ospace和-OTIme配合使用。

    · -O3 –OTIme:使用该选项编译的代码比-O2 –Otime选项编译的代码,在执行速度上要快,但占用的空间也更大。

    · -O3 -Ospace:产生的代码比使用-O2 -Ospace选项产生的代码尺寸小,但执行效率可能会差。

    如果要使编译的代码更侧重于代码的尺寸或执行效率(两者往往不可兼得),可以使用下面的编译选项。

    · -Ospace:指示编译程序执行优化,以延长执行时间为代价减小映像大小。例如,由外部函数调用代替内联函数。如果代码大小比性能更重要,则使用该选项。这是编译器的默认设置。

    · -Otime:指示编译程序执行优化,以增大映像大小为代价缩短执行时间。如果执行时间比代码大小更重要,则使用该选项。例如,它编译:

    while (expression) body;

    为:

    if (expression) {

    do body;

    while (expression);

    }

    如果既不指定-Otime也不指定-Ospace,则编译器默认使用-Ospace。可使用-Otime编译代码中对时间要求严格的部分,使用-Ospace编译其余部分。但不能在同一编译程序调用中同时指定-Otime和-Ospace。

    4.AAPCS选项

    ARM结构过程调用标准AAPCS(Procedure Call Standard for the ARM Architecture)是ARM体系结构二进制接口ABI(Application Binary Interface for the ARM Architecture【BSABI】)标准的一部分。使用该标准可以很方便的执行C和汇编语言的相互调用。

    编译程序时,使用--apcs选项可以指定所使用得AAPCS标准的版本。如果没有指定--apcs或--cpu选项,则编译器使用下面默认编译选项。

    --apcs /noswst/nointer/noropi/norwpi --cpu ARM7TDMI --fpu softvfp

    有关AAPCS的详细信息,请参加ARM相关文档。

    5.编译选项对代码生成影响示例

    本节举例说明编译器的优化选项如何影响代码生成。

    (1)使用-O0选项

    下面的例子显示了即使使用-O0编译选项对代码进行编译时,有些冗余代码还是会被编译器自动清除。

    int f(int *p)

    {

    return (*p = = *p);

    }

    使用armcc -c -O0对源程序进行编译,生成的汇编代码如下所示。

    f

    MOV r1, r0

    MOV r0, #1

    MOV pc, lr

    通过上面的例子可以看到,编译出的最终代码中没有加载(Load)指针P的值,变量*p被编译器优化掉了。如果不想让编译器对变量*p做优化,可以使用“volatile”对变量进行声明。下面的例子,显示了将变量声明为“volatile”类型后,使用armcc编译(-O2的优化级别)后的结果。

    f

    LDR r1,[r0]

    LDR r0,[r0]

    CMP r1,r0

    MOVNE r0,#0

    MOVEQ r0,#1

    MOV pc,lr

    另外,编译的代码中的“MOV r1, r0”并没有实际意义,只是为了方便调试程序时设置断点使用。

    (2)冗余代码的清除

    下面例子显示了一段急待优化的代码。

    int dummy()

    {

    int a=10, b=20;

    int c;

    c=a+b;

    return 0;

    }

    当使用arm –c –O0进行编译时,产生的汇编码如下所示。

    dummy:

    0000807C E3A0100A MOV r1,#0xa

    》》》 REDUNDANT\#3 int a=10,b=20;

    00008080 E3A02014 MOV r2,#0x14

    》》》 REDUNDANT\#5 c=a+b;

    00008084 E0813002 ADD r3,r1,r2

    》》》 REDUNDANT\#6 return 0;

    00008088 E3A00000 MOV r0,#0

    》》》 REDUNDANT\#7 }

    0000808C E12FFF1E BX r14

    从上面的汇编输出可以看到,编译器并没有对程序中的冗余变量做任何工作。但上面这段代码在编译时,编译器会给出警告,警告信息如下所示。

    Warning : #550-D: variable “c” was set but never used

    Redundant.c line 4 int c;

    但如果将编译器的优化级别提高,如使用arm –c –O1命令,则编译器输出的汇编代码如下所示。

    dummy:

    0000807C E3A00000 MOV r0,#0

    》》》 REDUNDANT\#7 }

    00008080 E12FFF1E BX r14

    从上面的例子看出,当优化级别提高到-O1时,程序中的冗余变量就会被清除。

    2137ekuV5Mscs2bUhCf%2FLgPTdWdwSQdOJ4r9AiBa%2Bfjp1bXKgeB4Dnngg2KrDc3P3bsAkrfgX9kyoKp6GmomvMjenj46upGq1jYyBQrWx1Zs5fJeHMNErZY%2Bc4vU4A

    (3)指令重排

    当指定编译器对程序代码进行优化时,编译器会对程序中排列不合理的汇编指令序列进行重排(只有在-O1及其以上的优化级别中才有),重排的目的是为了减少指令互锁(interload)。所谓互锁就是指如果一条指令需要前一条指令的执行结果,而这时结果还没有出来,那么处理器就会等待。这被称为流水线冒险(pipeline hazard),也被称为流水线互锁。

    下面例子显示了对同一程序使用代码重排和不使用代码重排所产生的汇编码的区别。÷

    程序的源代码如下所示。

    int f(int *p, int x)

    { return *p + x * 3; }

    使用-O0选项对代码进行编译(无代码重排),产生的结果如下所示。

    ADD r1,r1,r1,LSL #1

    LDR r0,[r0,#0]

    ADD r0,r0,r1 ; ARM9上产生互锁

    MOV pc,lr

    使用-O1选项对代码进行编译(存在代码重排),产生的结果如下所示。

    ADD r1,r1,r1,LSL #1

    ADD r0,r0,r1

    MOV pc,lr

    指令重排发生在寄存器定位和代码产生阶段。代码重排只对ARM9及其以后的处理器版本产生作用。当使用代码重排时,代码的执行速度平均提供4%。可以使用-zpno_optimize_

    scheduling编译选项关闭代码重排。

    (4)内嵌函数

    通常情况下,如果不指定编译选项,编译器会将一些代码量小且调用次数少的函数内嵌进调用函数中。如果某段子程序在其他模块中没有被调用,请使用Static关键字将其标识。

    编译选项的--autoinline和--no_autoinline可以作为内嵌函数的使能开关。--no_autoinline选项为-O0和-O1选项的默认选项,但如果指定-O2或-O3的优化选项,编译器将默认使用--autoinline选项。

    有关内嵌函数的详细信息,请参见本书内嵌函数一节。

    下面的例子显示了同一段程序,使用内嵌功能和不使用内嵌功能编译出的不同结果。

    要编译的源文件如下。

    int bar(int a)

    {

    a=a+5;

    return a;

    }

    int foo(int i)

    {

    i=bar(i);

    i=i-2;

    i=bar(i);

    i++;

    return i;

    }

    下面的汇编程序为不使用内嵌功能时编译出的结果。

    bar

    ADD r0,r0,#5

    MOV pc,lr

    foo

    STR lr,[sp,#-4]!

    BL bar

    SUB r0,r0,#2

    BL bar

    ADD r0,r0,#1

    LDR pc,[sp],#4

    下面的汇编码是使用内嵌功能时编译出的结果。

    foo

    ADD r0,r0,#5

    SUB r0,r0,#2

    ADD r0,r0,#5

    ADD r0,r0,#1

    MOV pc,lr

    从上面的例子可以看出在使用内嵌功能时,函数间的相互调用减少了数据的压栈和出栈,节省了程序的执行时间,但如果内嵌函数被调用多次会造成空间的浪费。

    以上内容便是小编此次带来的与c编译器相关的所有内容,如果你对本文比较满意,不妨在后期持续关注本网站的相关文章哦。

    展开全文
  • GCC编译器优化选项分析及具体优化了什么起因:目前项目使用nios IDE作为开发平台,其使用的编译器为gcc的交叉编译器。在设定编译条件时,在debug模式下生成的程序正常,但是在release模式下会出现LCD显示的开端显示...

    authorship.gif 

    GCC编译器优化选项分析及具体优化了什么

    起因:

    目前项目使用nios IDE作为开发平台,其使用的编译器为gcc的交叉编译器。在设定编译条件时,在debug模式下生成的程序正常,但是在release模式下会出现LCD显示的开端显示不全,缺少一个字节或字的状况。为了了解具体为什么造成该问题,对两种模式下的配置做了对比,编译器皆为nios2-elf-gcc交叉编译器,debug模式编译器参数为:-DALT_DEBUG-O0-g –Wall。release模式编译器参数为: -DALT_RELEASE -O2 -g –Wall。

    两种模式下的参数简单说明如下

    -DALT_DEBUG:目前没有明确资料显示该项的具体作用,根据命名可认为与调试有关选项。且两种模式下都有,暂时认为不会造成差异。

    -O0: gcc编译器默认优化等级。

    -g:gdb调试器支持选项用于在编译时生成相关调试信息。

    -Wall:打开所有编译器告警选项,即编译器最严格告警模式。

    -O2:gcc编译高于O0低于O3的编译优化选项。

    通过对比可以发现两种模式主要的不同在于编译器优化程度不同,那么编译器在两种优化下究竟做了什么优化那?是否由这些问题造成的显示丢失问题那??现在我们来看看gcc编译器的优化参数到底做了什么优化。(注:由于关于nios2-elf-gcc的文档资料十分稀少,不能形成可分析的文档,所以以通用的gcc作为分析,毕竟同出一源)

    正文:

    GCC编译器优化选项介绍:

    GCC编译器在目前是不是用最多的编译器也相去不远,尤其在嵌入式领域很多编译器都是基于GCC的cross gcc版本。毕竟功能成熟而且有开放的源代码。

    这里只介绍优化编译的参数

    -O用来开启优化编译选项。

    -O0:默认模式,不做任何优化。

    -O1:优化。该模式下对于一个大的函数或功能会花费更多的时间和内存。

    在-O1下:编译会尝试减少代码体积和代码运行时间。但是并不执行会花费大量时间的优化操作。

    在该模式下将打开一下优化选项:

    -fdefer-pop

    -fdelayed-branch

    -fguess-branch-probability

    -fcprop-registers

    -floop-optimize

    -fif-conversion

    -fif-conversion2

    -ftree-ccp

    -ftree-dce

    -ftree-dominator-opts

    -ftree-dse

    -ftree-ter

    -ftree-lrs

    -ftree-sra

    -ftree-copyrename

    -ftree-fre

    -ftree-ch

    -funit-at-a-time

    -fmerge-constants

    该模式下在不影响调试的状况下还会打开‘-fomit-frame-pointer优化项。

    同时该模式不会为Ada编译器打开‘-ftree-sra’优化项,如需要则请使用命令参数输入‘-ftree-sra’进行优化。

    -O2:进一步优化.GCC执行几乎所有支持的操作但不包括空间和速度之间权衡的优化。-O2优化等级下,并不执行循环展开和函数“内联”【注1】优化操作。与-O1比较该优化-O2将会花费更多的编译时间当然也会生成性能更好的代码。-O2除了打开-O1的所有优化参数外还打开以下优化选项。

    -fthread-jumps

    -fcrossjumping

    -foptimize-sibling-calls

    -fcse-follow-jumps -fcse-skip-blocks

    -fgcse -fgcse-lm

    -fexpensive-optimizations

    -fstrength-reduce

    -frerun-cse-after-loop -frerun-loop-o

    -fcaller-saves

    -fpeephole2

    -fschedule-insns -fschedule-insns2

    -fsched-interblock -fsched-spec

    -fregmove

    -fstrict-aliasing

    -fdelete-null-pointer-checks

    -freorder-blocks -freorder-functions

    -falign-functions -falign-jumps

    -falign-loops -falign-labels

    -ftree-vrp

    -ftree-pre

    还要注意-fgcse下关于请求-O2优化等级的用于计算goto的程序。

    -O3:更进一步优化。-O3打开-O2指定的所有优化操作并且打开:

    -finline-functions

    -funswitch-loops

    -fgcse-after-reload

    优化项。

    -Os:针对程序空间大小优化(多用于嵌入式系统)。-Os使能-O2中除去会增加程序空间的所有优化参数。同时-Os还会执行更加优化程序空间的选项。

    -Os会关闭以下优化选项:

    -falign-functions

    -falign-jumps

    -falign-loops

    -falign-labels

    -freorder-blocks

    -freorder-blocks-and-partition

    -fprefetch-loop-arrays

    -ftree-vect-loop-version

    关于GCC编译的优化选项一共有-O0(默认),-O1,-O2,-O3及-Os五个参数。各个参数优选内容如上所示。但是各个优化内容到底是指什么那?继续分析。

    2.优化具体参数含义。(共计49项)

    -fdefer-pop

    推迟推出函数调用的参数,对于那些需要在函数调用后必须取出(pop)函数参数的机器而言,打开该项编译器将把函数调用的参数压入栈,等必要时几个函数调用参数一起取出(pop)。这将节省处理时间。

    -fdelayed-branch

    如果对目标机支持这个功能,它试图重新排列指令,以便利用延迟分支(delayed branch)指令后面的指令空隙.

    -fguess-branch-probability

    使用启发式算法预测分之指令,增加指令的命中率,提升运行效果。

    -fcprop-registers

    使用寄存器之间copy-propagation传值;

    因为在函数中把寄存器分配给变量, 所以编译器执行第二次检查以便减少

    调度依赖性(两个段要求使用相同的寄存器)并且删除不必要的寄存器复制操作

    -floop-optimize

    过优化如何生成汇编语言中的循环, 编译器可以在很大程序上提高应用程序的性能。 通常, 程序由很多大型且复杂的循环构成。

    通过删除在循环内没有改变值的变量赋值操作, 可以减少循环内执行指令的数量, 在很大程度上提高性能。 此外优化那些确定何时离开循环的条件分支,

    以便减少分支的影响。

    -fif-conversion

    if-then语句应该是应用程序中仅次于循环的最消耗时间的部分。

    简单的if-then语句可能在最终的汇编语言代码中产生众多的条件分支。 通过减少

    或者删除条件分支, 以及使用条件传送 设置标志和使用运算技巧来替换他们, 编译

    器可以减少if-then语句中花费的时间量。

    -fif-conversion2

    这种技术结合更加高级的数学特性, 减少实现if-then语句所

    需的条件分支。

    -ftree-ccp

    Perform sparse conditional constant propagation (CCP) on trees. This pass

    only operates on local scalar variables and is enabled by default at ‘-O’  and

    higher.

    -ftree-dce

    编译器将消除无用的不会被执行的代码(dead code)

    -ftree-dominator-opts

    Perform a variety of simple scalar cleanups (constant/copy propagation, redun-

    dancy elimination, range propagation and expression simplification) based on a

    dominator tree traversal. This also performs jump threading (to reduce jumps

    to jumps). This flag is enabled by default at ‘-O’ and higher.

    -ftree-dse

    -ftree-ter

    Perform temporary expression replacement during the SSA->normal phase. Sin-

    gle use/single def temporaries are replaced at their use location with their defin-

    ing expression. This results in non-GIMPLE code, but gives the expanders

    much more complex trees to work on resulting in better RTL generation. This

    is enabled by default at ‘-O’ and higher.

    -ftree-lrs

    Perform live range splitting during the SSA->normal phase. Distinct live ranges

    of a variable are split into unique variables, allowing for better optimization

    later. This is enabled by default at ‘-O’ and higher.

    -ftree-sra

    -ftree-copyrename

    -ftree-fre

    -ftree-ch

    -funit-at-a-time

    -fmerge-constants

    -fthread-jumps

    -fcrossjumping

    -foptimize-sibling-calls

    -fcse-follow-jumps

    -fcse-skip-blocks

    -fgcse -fgcse-lm

    -fexpensive-optimizations

    -fstrength-reduce

    -frerun-cse-after-loop

    -frerun-loop-o

    -fcaller-saves

    -fpeephole2

    -fschedule-insns

    -fschedule-insns2

    -fsched-interblock

    -fsched-spec

    -fregmove

    -fstrict-aliasing

    -fdelete-null-pointer-checks

    -freorder-blocks

    -freorder-functions

    -falign-functions

    -falign-jumps

    -falign-loops

    -falign-labels

    -ftree-vrp

    -ftree-pre

    -finline-functions

    允许编译器选择某些简单的函数在其被调用处展开,比较安全的选项,特别是在CPU二级缓存较大时建议使用。

    -funswitch-loops

    -fgcse-after-reload

    展开全文
  • 编译器优化机制详解

    千次阅读 2021-09-02 04:40:09
    当你了解了Java的即时编译器,不仅能够轻松回答上述问题,还能如数家珍的讲出JVM在即时编译器上采用的优化技术,而且在实践过程中更深刻的理解代码背后的原理。 字节码是如何运行的 先来探讨字节码是如何运行的。...
  • 编译器优化等级简述

    千次阅读 2022-02-13 12:59:31
    编译优化,会使编译器尝试以牺牲编译时间和调试程序的能力为代价,来提高性能或代码大小; 合理的优化级别,能够在代码体积、执行性能、RAM占有率上获得均衡! ... 优化级别说明 GCC优化级别有-O0、-O1、-O2、-O3、-Og、-...
  • 编译器优化详解

    2021-06-20 10:06:08
    文章目录一、解释vs编译二、c1编译器三、c2编译器四、分层编译五、如何找到热点代码 一、解释vs编译 Java是混合模式执行的 二、c1编译器 三、c2编译器 c1编译器比较适合客户端带图形界面。 c2编译器比较适合...
  • C++编译器优化

    2021-09-28 15:29:26
    C++编译器优化,有优化选项,三个级别,O0,O1, O2 这里我想说的是另外一种优化,专门针对于构造函数的返回值优化RVO,Return Value Optimization。 利用-fno-elide-constructors选项在g++中关闭这个优化。 ...
  • 作者 | 江贺 整理 | Hana 作者简介: 江贺,大连理工大学软件学院教授,博士生导师,研究领域:智能软件工程(软件大数据处理、编译系统测试、...哔哩哔哩,,编译器优化故障的测试与定位小程序 # Introducti...
  • 软件上则分为 编译器优化和程序员优化: 程序员优化: 程序员对程序算法、逻辑顺序进行合理安排。 程序员优化是程序员在编写代码时,对代码的算法、逻辑顺序进行合理安排,提升效率; 编译器优化: 编译器编译时会调整...
  • IAR开发环境 编译器优化 STM8代码优化
  • 所有的代码转化为可执行文件...本文通过分析Go编译器优化的完整案例,向大家分享编译器的编译规则的优化方法。 摘自OptimizeLab:https://github.com/OptimizeLab/docs 作者:surechen 编译器的作用是将高级语言...
  • volatile关键字是一种类型修饰符,用它声明的类型变量,编译器对访问该变量...编译器的优化在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就...
  • 一、优化屏障 ( 编译器优化 | CPU 执行优化 )、 二、优化屏障源码
  • 编译器优化游乐场(希望)这是经典的寄存器机器中间表示(IR)的最简单实现,用于在编译器中端进行数据和控制流分析。项目目的对于希望通过玩耍并实施各种编译器分析和转换过程来扩展知识的人们来说,这是一个经典的...
  • 关于C/C++编译器的默认优化以及volatile关键字的使用 今天刷题,由于自己的粗心,讲赋值号写成==了,导致编译器把某段代码优化,而出了一个很诡异的bug,故提笔记之 请看代码 for(int len=1;len<=n;len++){ for...
  • 编译器优化及优化问题的调试方法

    千次阅读 2019-08-16 08:46:18
    gcc 优化影响了那些内容 Debug Optimized code 局部变量 从栈里面分配到使用寄存器到直接移除。局部变量只是临时保存中间的计算结果,可以直接优化掉,则调试时不能看到局部变量的值 函数中的语句的位置 语句的...
  • 123 //编译器优化 456 123 //编译器优化 后面2个123是因为编译器加了优化,看到是const和constexpr就直接把结果输出为123了。 采用g++ -O0 const1.cpp 关掉编译器优化,效果还是一样。可能有些平台上可以。 #include...
  • 主要介绍了C#中尾递归的使用、优化及编译器优化,本文讲解了递归运用、尾递归优化、编译器优化等内容,需要的朋友可以参考下
  • 字节跳动青训营Day04 - Go编译器优化1.编译器和静态分析编译器的结构2.Go 编译器优化目的现状思路函数内联逃逸分析 1.编译器和静态分析 编译器的结构 静态分析:不执行代码,推导程序的行为,分析程序的性质。 控制...
  • Keil的编译器优化级别和调试视图 Compiler User Guide: Compiler optimization levels and the debug view 编译器执行的精确优化取决于选择的优化级别,以及您是针对性能还是代码大小进行优化。 编译器支持以下优化...
  • C/C++ 编译器优化介绍

    2020-08-29 05:45:35
    主要涉及了C/C++ 编译器优化的简单介绍,具有一定参考价值。如有不对之处,欢迎指出。
  • 踩坑编译器优化问题

    2020-05-13 21:09:13
    最近在调试自己画的板子时,又再次遇到了变量被编译器优化的问题。虽然不是第一次遇到这个问题了,但还是花了一些时间才定位到这个点。为了警醒自己,避免再在这个问题上浪费时间,特记录下来。 问题描述: 调试...
  • GoLang之编译器和静态分析、Go 编译器优化、逃逸分析
  • C语言 之编译器优化

    千次阅读 2020-03-23 20:15:16
    C语言的编译器会对变量和代码进行一定的优化,我们看下面这个例子。 int a,b,c; a=1; b=a; c=b; 这个程序正常运行的时候会这样子:先把a指向的内存空间内放入1 再把a指向的内存空间里的数读出来放到b指向的...
  • 一个CocoaPods插件,用于禁用特定Pod的所有编译器优化。 为什么? 因此,您正在编写一个受欢迎的新应用,并且需要一个外部依赖项。 您想使用的库可作为CocoaPod使用-太棒了! 但这是用Swift编写的。 好东西...
  • 作者通过查询、试验发现:使用Intel编译器优化中尺度模式MM5,能够使得MM5在奔腾4上的运行速度提高1.4~1.5倍。利用Intel编译器优化后的MM5模式,进行了三个月资料的计算,模式运行稳定。给出了一个使用Intel编译器和...
  • 矩阵计算的布局无关编译器优化

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 330,636
精华内容 132,254
关键字:

编译器优化

友情链接: MUSIC.rar