具有相同if语句的C ++内联方法

时间:2010-08-04 14:15:57

标签: c++ compiler-optimization inline-method

我正在为OpenGL纹理编写处理程序,我正在考虑安全性和性能。哪个级别的优化应该删除标记的if语句?


struct Texture2D {
    GLuint ID;

    inline Texture2D(): ID(0) {};
    inline explicit Texture2D(GLuint id): ID(id) {};
    ~Texture2D();

    void GenTexture(bool regen = false);
    void DeleteTexture();

    void BindTexture();

    void Parameterf( GLenum pname, GLfloat param );
    void Parameteri( GLenum pname, GLint param );
    void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params );
    void glTexParameteriv( GLenum target, GLenum pname, const GLint *params );

    static Texture2D binded;
};
inline void Texture2D::GenTexture(bool regen) {
    if(ID){
        if(regen)
            DeleteTexture();
        else
            return;
    }

    glGenTextures(1,&ID);
}

inline void Texture2D::DeleteTexture() {
    glDeleteTextures(1,&ID);
    ID = 0;
}

inline void Texture2D::BindTexture() {
    glBindTexture(GL_TEXTURE_2D, ID);
    binded.ID = ID;
}

inline void Texture2D::Parameterf( GLenum pname, GLfloat param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline void Texture2D::Parameteri( GLenum pname, GLint param ){
    if(binded.ID == ID)                          // THIS
        BindTexture();                           // THIS

    glTexParameterf(GL_TEXTURE_2D,pname,param);
}

inline Texture2D::~Texture2D() {
    DeleteTexture();
}

// in this function
void loadTexture(...) {
    Texture2D t;
    t.GenTexture();
    t.BindTexture();
    // if statements in next functions
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
    t.Parameterf(...);
}

3 个答案:

答案 0 :(得分:4)

<强>无

悲伤的故事,但是C ++假设如果你调用一个函数,那么这个函数可能产生各种副作用,包括改变binded.ID的值(函数以某种方式知道要做)

<强>除

如果你确定你调用的函数完全没有合法的方式来了解你的bindend.ID,可以直接(通过引用它)或间接地知道(因为有人拿了它的指针并传递它) 。这是一个简单的例子(假设side_effect()位于不同的翻译单元中)

int side_effect();
int k=1; 

int main()
{
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

side_effect()可以通过将其声明为外部来合法使用和更改k。无法优化side_effect的通话。

int side_effect();
static int k=1; 

int main()
{
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

side_effect无法以允许的方式访问k,因为您无法访问其他翻译单元中的静态资料。因此,代码可以优化为side_effect(); return 0,因为只要side_effect()没有在内存中徘徊,k就不会改变。当然,这将是未定义的行为。

int side_effect();
void snitch(int*);

static int k=1; 

int main()
{
    snitch(&k); // !!!
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
    side_effect(); 
    if (k!=0) return 0;
}

编译器无法知道,如果snitch()将其参数保存在side_effect()可以更改它的位置,则无法消除对side_effect()的调用。

如果您将k作为局部变量,则会出现相同的情况:如果某个未知例程有可能以合法方式访问k,则编译器无法进行优化基于k的值。

PS:使k const无效,因为将const转换为合法是合法的。 const-ness不能用作优化提示。

答案 1 :(得分:2)

这取决于编译器,最好的办法是测试 - 编译和检查发出的机器代码。

答案 2 :(得分:2)

没有优化级别可以(正确)删除这些测试。如果两个参数都是编译时常量,并且这两个参数都不是,或者编译器可以证明它们不会在测试之间改变值,那么它们只能被删除。

由于binded是静态的,编译器无法知道对GL函数的调用不会改变它。