Tag: 编译器优化

GCC 5.1循环展开

给出以下代码 #include int main(int argc, char **argv) { int k = 0; for( k = 0; k < 20; ++k ) { printf( "%d\n", k ) ; } } 使用GCC 5.1或更高版本 -xc -std=c99 -O3 -funroll-all-loops –param max-completely-peeled-insns=1000 –param max-completely-peel-times=10000 部分循环展开,它将循环展开十次然后进行条件跳转。 .LC0: .string “%d\n” main: pushq %rbx xorl %ebx, %ebx .L2: movl %ebx, %esi movl $.LC0, […]

由main()修改并由ISR()访问的全局变量

这是我的c代码 char global_variable = 0; ISR(){ PORTA = global_variable; toggle_led;//to make sure that the interrupt is triggered } int main(){ while(1){ _delay_ms(500); gobal_variable++; PORTB = global_variable; } return 0; } 底线是我有一个由main函数修改的全局变量,并由main和ISR – 中断处理程序读取。 当main读取全局变量时,我得到期望的值,但在ISR中,我得到第一次分配给全局变量的值。 我知道这是一个优化问题,但我不明白是什么让编译器看到主要的正确值和ISR中的初始值 注意:当我在ISR中修改变量时,我在ISR中读取它,但在主要中我得到了初始值。

为什么main在没有变量时初始化堆栈帧

为什么这个代码: #include “stdio.h” int main(void) { puts(“Hello, World!”); } 决定初始化堆栈帧? 这是汇编代码: .LC0: .string “Hello, World!” main: push rbp mov rbp, rsp mov edi, OFFSET FLAT:.LC0 call puts mov eax, 0 pop rbp ret 为什么编译器初始化一个堆栈帧只是为了以后它被销毁,而它是否曾经被使用过? 这肯定不会导致主函数外部的任何错误,因为我从不使用堆栈,所以我不会导致任何错误。 为什么这样编译?

gcc -ffp-contract选项的差异

我对GNU GCC中的-ffp-contract标志有疑问(参见https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html )。 标志文档编写如下: -ffp-contract=off禁用浮点表达式收缩。 -ffp-contract=fast启用浮点表达式收缩,例如,如果目标具有对它们的本机支持,则形成融合乘法 – 加法运算。 -ffp-contract=on如果语言标准允许,则启用浮点表达式收缩。 目前尚未实施和处理等于-ffp-contract=off 。 默认值为-ffp-contract=fast 。 现在的问题是: 快速和开启有什么区别? FMA旁边是否还有其他收缩示例(或类似于融合多子类)?

函数仅在标题中定义时才会内联。 我错过了什么吗?

使用gcc v4.8.1 如果我做: //func.hpp #ifndef FUNC_HPP #define FUNC_HPP int func(int); #endif //func.cpp #include “func.hpp” int func(int x){ return 5*x+7; } //main.cpp #include #include “func.hpp” using std::cout; using std::endl; int main(){ cout<<func(5)<<endl; return 0; } 即使是简单的函数func也不会内联。 原型和/或定义上没有inline , extern , static和__attribute__((always_inline))的组合改变了这一点(显然这些说明符的某些组合导致它甚至不编译和/或产生警告,而不是讨论那些) 。 我正在使用g++ *.cpp -O3 -o run和g++ *.cpp -O3 -S来进行汇编输出。 当我查看程序集输出时,我仍然看到call func 。 它似乎只有我能够正确内联函数的方法是拥有原型(可能没有必要)和头文件中函数的定义。 如果标题仅包含在整个程序中的一个文件中(例如仅由main.cpp包含),则它将进行编译,并且函数将被正确内联,甚至不需要inline说明符。 如果要将标头包含在多个文件中,则似乎需要inline说明符来解决多个定义错误,这似乎是其唯一目的。 […]

编译器是否注意像if(0)这样无用的代码?

最近,我正在编译Windows下的ffmpeg代码使用带有intel编译器的VS2010。 对于以下代码: void ff_dcadsp_init(DCADSPContext *s) { s->lfe_fir = dca_lfe_fir_c; if (ARCH_ARM) ff_dcadsp_init_arm(s); } 宏ARCH_ARM定义为0 。 当我在linux下编译它时,目标文件中的ff_dcadsp_init_arm()中没有函数,而它在windows下呢? 所以我想确定编译器是否会对无用的代码做些什么,以及如何为INTEL编译器设置它。

没有与GCC的内存对齐

我正在处理一些分组数据。 我创建了用于保存数据包数据的结构。 这些结构是由python为特定的网络协议生成的。 问题在于,由于编译器对齐结构这一事实,当我通过网络协议发送数据时,消息最终会比我想要的更长。 这会导致其他设备无法识别该命令。 有没有人知道可以解决这个问题,这样我的打包器的大小应该是结构应该的大小,还是有办法可以关闭内存对齐?

确定预处理器中的优化级别?

-Og是一个相对较新的优化选项,旨在改进应用优化时的调试体验。 如果用户选择-Og ,那么我希望我的源文件激活备用代码路径以增强调试体验。 GCC提供__OPTIMIZE__预处理器宏 ,但只有在优化生效时才将其设置为1。 有没有办法学习优化级别,如-Og , -O3或-Og ,以便与预处理器一起使用?

C ++ while循环优化不能正常工作

我有这段代码: #include int main(int argc, const char** argv) { int a = argv[0][0]; int b = argv[0][1]; while ((a >= 0) && (a < b)) { printf("a = %d\n", a); a++; } return 0; } 我用gcc-4.5 -02 -Wstrict-overflow=5编译它。 编译器向我大吼大叫warning: assuming signed overflow does not occur when changing X +- C1 cmp C2 to X cmp […]

为什么GCC在这个例子中没有发出警告

启用-Wsequence-point ,GCC应在发现未定义的行为代码时警告用户。 例如 b = a + ++a; 应该被GCC注意到并且应该被报告为“未定义的行为”代码(因为ISO C没有指定评估操作数的顺序)。 但是,我玩了语法,我尝试了这个: int *a = malloc(sizeof(int) * 2); a[0] = 1; printf(“%d\n”, *(a + (*a)++ – *a)); 当然,我收到了警告 警告:’* a’上的操作可能未定义[-Wsequence-point] 这是我所期望的,因为*a (其为a[0] )的值可以在处理第三个操作数时递增或者可以不递增。 但是,我尝试了以下一个: int *a = malloc(sizeof(int) * 2); a[0] = 1; printf(“%d\n”, *(a + (*a)++ – 1)); 我很惊讶,因为我没有收到任何警告。 这不应该是UB吗? 我的意思是,根据ISO C99,可以在表达式评估期间的任何点评估后增量操作(逗号运算符和三元运算符除外)。 在我的后一个例子中,我没有递增指针,而是指向它指向的整数。 因此,根据标准,它可以在任何点递增(这意味着它可以在评估整个表达式后递增),因此程序可以打印1或2 ,对吧? […]