2017-06-11 13 views
0

私が書いているプログラムには、10個のグローバル関数ポインタが含まれていました。私はそれから、2つの関数を呼び出した後に生成されたマシンコードが変更されるかどうかを調べるために、それらをstructに入れることにしました。構造体を使用するコードのバージョンに、構造体がないコードのバージョンより2つ多くの移動命令が含まれていることに驚きました(逆アセンブリのすべての行は同じです)。これは奇妙な最適化のいくつかの種類ですか、またはコンパイラは構造体メンバ呼び出しのオーバーヘッドを排除する方法を知らないのですか?私はコンパイラとしてClang 3.8を使用しており、x86用にコンパイルしています。構造体なしCまったく簡単な最適化が完了していない

#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); 
} 

バージョン:構造体で

バージョンは

int prepareShader(GLuint shaderType, const char * shaderCode) { 
    GLuint shader = glCreateShader(shaderType); 
    int len = strlen(shaderCode); 
    glShaderSource(shader, 1, &shaderCode, &len); 
    return shader; 
} 

これは、メインの関数呼び出しです:

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 vertexShader = prepareShader(GL_VERTEX_SHADER, VERTEX_SHADER); 
//VERTEX_SHADER is a string in my code 

答えて

1

構造体自体にオーバーヘッドはありません。 const構造体を直接呼び出しに最適化されるはずです:構造体は、constのではない場合

https://godbolt.org/g/gBNnp3

、ポインタ値は、最初にロードされますする必要があります。パディングが必要な場合は、シンボルのオブジェクトコード出力も若干異なる場合があります(10個の関数で試してみると、call1は末尾にxchg %ax %ax == nopとなります)。

関連する問題