C看似琐碎的优化没有完成
我正在编写的一个程序包含10个全局函数指针。然后我决定将它们放在一个结构中,看看这是否会改变调用其中两个函数后生成的机器代码。我惊讶地发现,使用结构的代码版本比不使用结构的代码版本多包含两条move指令(反汇编的所有其他行都是相同的)。这是某种奇怪的优化,还是编译器不知道如何消除结构成员调用的开销?我使用Clang3.8作为编译器,并为x86进行编译 具有结构的版本:C看似琐碎的优化没有完成,c,opengl-es-2.0,compiler-optimization,llvm-clang,C,Opengl Es 2.0,Compiler Optimization,Llvm Clang,我正在编写的一个程序包含10个全局函数指针。然后我决定将它们放在一个结构中,看看这是否会改变调用其中两个函数后生成的机器代码。我惊讶地发现,使用结构的代码版本比不使用结构的代码版本多包含两条move指令(反汇编的所有其他行都是相同的)。这是某种奇怪的优化,还是编译器不知道如何消除结构成员调用的开销?我使用Clang3.8作为编译器,并为x86进行编译 具有结构的版本: #include GLES2/gl2.h struct GLES2FunctionPointers { const P
#include GLES2/gl2.h
struct GLES2FunctionPointers {
const PFNGLCLEARCOLORPROC glClearColor;
const PFNGLCREATEPROGRAMPROC glCreateProgram;
};
struct GLES2FunctionPointers GLES2 = {
.glCreateProgram =
(PFNGLCREATEPROGRAMPROC)eglGetProcAddress("glCreateProgram"),
.glCreateShader =
(PFNGLCREATESHADERPROC)eglGetProcAddress("glCreateProgram"),
};
GL_APICALL GLuint GL_APIENTRY glCreateShader(GLenum type) {
return GLES2.glCreateShader(type);
}
GL_APICALL void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const
GLchar *const*string, const GLint *length) {
GLES2.glShaderSource(shader, count, string, length);
}
不带结构的版本:
const PFNGLCREATESHADERPROC glCreateShaderPointer = (PFNGLCREATESHADERPROC)eglGetProcAddress("glCreateShader");
GL_APICALL GLuint GL_APIENTRY glCreateShader(GLenum type) {
return glCreateShaderPointer(type);
}
const PFNGLSHADERSOURCEPROC glShaderSourcePointer =
(PFNGLSHADERSOURCEPROC)eglGetProcAddress("glCreateProgram");
GL_APICALL void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count,
const GLchar *const*string, const GLint *length) {
glShaderSourcePointer(shader, count, string, length);
}
这是正在拆解的功能:
int prepareShader(GLuint shaderType, const char * shaderCode) {
GLuint shader = glCreateShader(shaderType);
int len = strlen(shaderCode);
glShaderSource(shader, 1, &shaderCode, &len);
return shader;
}
这是main中的函数调用:
int vertexShader = prepareShader(GL_VERTEX_SHADER, VERTEX_SHADER);
//VERTEX_SHADER is a string in my code
结构本身没有开销<代码>常量结构应优化为直接调用: 如果结构不是常量,则需要首先加载指针值。如果需要填充,符号的目标代码输出也可能略有不同(如果我尝试使用十个函数,
call1
在末尾获得一个xchg%ax%ax
=nop
)