GCC优化级别大于0时输出近乎空的汇编文件问题求助
问题原因与解决办法
你遇到的这个问题其实很常见——GCC在优化级别大于0时,把你的integral_image函数彻底删掉了!
为什么会出现空汇编文件?
你的integral_image是静态函数(用static修饰),而且整个程序里没有任何地方调用它。GCC从-O1开始会启用死代码消除优化,对于这种未被使用的静态函数,编译器会判定它是“无用代码”,直接从编译结果中移除,所以最终的汇编文件里只剩一些文件标识和栈相关的注释,完全看不到函数的机器码。
解决方法(任选其一即可)
1. 添加函数调用(最推荐)
在代码里加上一个main函数,调用integral_image,哪怕是简单的测试调用:
#include <math.h> #include <stdio.h> #include <stdlib.h> #define HEIGHT 2000 #define WIDTH 1000 static unsigned int idx(unsigned int x, unsigned int y, unsigned int stride){ return y * stride + x; } static void integral_image(const unsigned char * restrict in, unsigned int * restrict out){ unsigned int row_sum = 0; unsigned char *newin = __builtin_assume_aligned(in, 16); unsigned int *newout = __builtin_assume_aligned(out, 16); // 修正类型不匹配问题 for(unsigned int x = 0; x < WIDTH; ++x){ row_sum += newin[x]; newout[x] = row_sum; } for(unsigned int y = 1; y < HEIGHT; ++y){ row_sum = 0; for(unsigned w = 0; w < WIDTH; w += 4){ const unsigned int i1 = idx(w, y, WIDTH); const unsigned int old1 = idx(w, y - 1, WIDTH); const unsigned int i2 = idx(w + 1, y, WIDTH); const unsigned int old2 = idx(w + 1, y - 1, WIDTH); // 修正索引错误 const unsigned int i3 = idx(w + 2, y, WIDTH); const unsigned int old3 = idx(w + 2, y - 1, WIDTH); const unsigned int i4 = idx(w + 3, y, WIDTH); const unsigned int old4 = idx(w + 3, y - 1, WIDTH); row_sum += newin[i1]; newout[i1] = row_sum + newout[old1]; row_sum += newin[i2]; newout[i2] = row_sum + newout[old2]; row_sum += newin[i3]; newout[i3] = row_sum + newout[old3]; row_sum += newin[i4]; newout[i4] = row_sum + newout[old4]; } } } int main() { // 分配测试内存并调用函数 unsigned char *in = malloc(WIDTH * HEIGHT); unsigned int *out = malloc(WIDTH * HEIGHT * sizeof(unsigned int)); if (in && out) { integral_image(in, out); free(in); free(out); } return 0; }
编译时用gcc-7 -O2 -S thrash.c,就能看到完整的函数汇编代码了。另外我帮你修正了代码里的两个小问题:newout的类型应该是unsigned int*(和参数out匹配),以及old2的索引写错了,应该对应w+1的位置。
2. 强制保留未使用的静态函数
如果不想加main函数,可以给静态函数加上__attribute__((used))属性,告诉编译器这个函数必须被保留,即使没有被调用:
static void __attribute__((used)) integral_image(const unsigned char * restrict in, unsigned int * restrict out){ // 函数实现不变 }
然后用gcc-7 -O2 -S thrash.c编译,就能在汇编文件里看到这个函数的代码了。
3. 用编译选项强制保留
也可以通过编译选项直接告诉GCC不要移除未使用的静态函数:
gcc-7 -O2 -fkeep-static-functions -S thrash.c
额外提示:查看向量化情况
除了看汇编代码,你还可以用GCC的向量化诊断选项,直接查看是否成功向量化:
gcc-7 -O2 -ftree-vectorize -fopt-info-vec-all thrash.c
这个命令会输出详细的向量化日志,告诉你哪些循环被向量化了,哪些没有,以及具体原因,比直接看汇编更直观。
内容的提问来源于stack exchange,提问作者Hackerman
相关产品推荐
相关产品推荐

