Tag: 编译器优化

C – 编译器优化如何影响没有主体的for循环?

我有一些遗留代码,其中包含了一个时间浪费循环,以便有时间让eeprom读取完成(不良做法): for(i = 0; i < 50; i++); 但是,当编译器优化开启以获得速度时,会发生特殊情况。 它不一定与该语句相关联,但我想知道编译器是否可能只是优化时间延迟

为什么GCC没有优化对printf的这个调用?

#include int main(void) { int i; scanf(“%d”, &i); if(i != 30) { return(0); } printf(“i is equal to %d\n”, i); } 结果字符串似乎总是“我等于30”,那么,为什么GCC不会通过调用puts()或write()来优化对printf的调用? (刚刚使用gcc -O3 (版本5.3.1)或Godbolt Compiler Explorer检查生成的程序集)

无限循环条件变量是否应始终声明为volatile?

考虑一下这种类型的代码, while( !cond ) ; 如果cond未声明为volatile,则编译器可以通过将其缓存在寄存器中来优化它。 在这种情况下,即使在设置cond后,while循环也将继续。 现在这是否意味着任何此类变量应始终声明为volatile ? 为什么编译器不够聪明才能意识到它不应该缓存这些变量?

为什么编译器会假设这些看似相等的指针有所不同?

看起来GCC有一些优化认为来自不同翻译单元的两个指针永远不会相同,即使它们实际上是相同的。 码: main.c中 #include #include int a __attribute__((section(“test”))); extern int b; void check(int cond) { puts(cond ? “TRUE” : “FALSE”); } int main() { int * p = &a + 1; check( (p == &b) == ((uintptr_t)p == (uintptr_t)&b) ); check(p == &b); check((uintptr_t)p == (uintptr_t)&b); return 0; } 公元前 int b __attribute__((section(“test”))); 如果我用-O0编译它,它会打印出来 TRUE […]

为什么即使使用volatile关键字,编译器也会因strncmp()而优化掉共享内存读取?

这是一个程序foo.c ,它将数据写入共享内存。 #include #include #include #include #include #include #include #include int main() { key_t key; int shmid; char *mem; if ((key = ftok(“ftok”, 0)) == -1) { perror(“ftok”); return 1; } if ((shmid = shmget(key, 100, 0600 | IPC_CREAT)) == -1) { perror(“shmget”); return 1; } printf(“key: 0x%x; shmid: %d\n”, key, shmid); if ((mem = […]

C / C ++不确定值:编译器优化提供不同的输出(示例)

看起来C / C ++编译器(clang,gcc等)产生与优化级别相关的不同输出。 您也可以查看这篇文章中包含的在线链接。 http://cpp.sh/5vrmv (将输出从none更改为-O3以查看差异)。 根据以下代码,有人可以解释我的一些问题: #include #include int main(void) { int *p = (int *)malloc(sizeof(int)); free(p); int *q = (int *)malloc(sizeof(int)); if (p == q) { *p = 10; *q = 14; printf(“%d”, *p); } return 0; } 是否确定执行将始终进入if语句? 我们怎么知道两个指针p和q的地址是一样的? 为什么没有优化有输出14 ,而-O3有相同指令的输出10 ?

强制GCC执行memcpy运行时大小检查的循环非开关?

是否有任何可靠的方法强制GCC(或任何编译器)在循环外的memcpy()中memcpy()运行时大小检查(其中该大小不是编译时常量,但在该循环内是常量),专门针对每个循环相关的尺寸范围而不是反复检查其中的尺寸? 这是一个测试案例,从这里报告的性能回归中减少了一个开源库,该库旨在用于大数据集的高效内存分析。 (回归恰好是因为我的一个提交…) 原始代码在Cython中,但我已将其简化为纯C代理,如下所示: void take(double * out, double * in, int stride_out_0, int stride_out_1, int stride_in_0, int stride_in_1, int * indexer, int n, int k) { int i, idx, j, k_local; k_local = k; /* prevent aliasing */ for(i = 0; i < n; ++i) { idx = indexer[i]; for(j = 0; j < […]

gcc删除内联汇编程序代码

似乎gcc 4.6.2删除了它认为从函数中未使用的代码。 test.c的 int main(void) { goto exit; handler: __asm__ __volatile__(“jmp 0x0”); exit: return 0; } main()拆卸 0x08048404 : push ebp 0x08048405 : mov ebp,esp 0x08048407 : nop # <– This is all whats left of my jmp. 0x08048408 : mov eax,0x0 0x0804840d : pop ebp 0x0804840e : ret 编译器选项 没有启用优化,只有gcc -m32 -o test test.c […]

让GCC在没有内联汇编的情况下使用进位逻辑进行任意精度算术?

使用任意精度算术(例如512位整数)时,有没有办法让GCC在不使用内联汇编的情况下使用ADC和类似指令? 乍一看GMP的源代码显示,它们只是为每个支持的平台提供了汇编实现。 这是我编写的测试代码,它从命令行添加两个128位数字并打印结果。 (受mini-gmp的add_n启发): #include #include #include int main (int argc, char **argv) { uint32_t a[4]; uint32_t b[4]; uint32_t c[4]; uint32_t carry = 0; for (int i = 0; i < 4; ++i) { a[i] = strtoul (argv[i+1], NULL, 16); b[i] = strtoul (argv[i+5], NULL, 16); } for (int i = 0; i < 4; […]

C编程:从汇编程序的角度来看++ i和i = i + 1之间的区别?

这是一个面试问题。 我说他们是一样的,但这被判定为不正确的回应。 从汇编程序的角度来看,有什么可以想象的区别吗? 我使用默认的gcc优化和-S编译了两个简短的C程序来查看汇编器输出,它们是相同的。