【问题标题】:gcc const and optimization across function callsgcc const 和跨函数调用的优化
【发布时间】:2016-02-13 21:50:14
【问题描述】:

考虑这段代码,用gcc-Ofast 编译:

int f1(const char *p) {
    if (!p[0])
        return 0;

    f2(); //not inlined

    if (p[0]) { //not optimized out
        //do something
        return 0;
    } else {
        //do something else
        //not optimized out
        return 1;
    }
}

如何获得优化第二个测试和较低分支的行为(因为 p[0]const 并且已经过测试)?

【问题讨论】:

  • const 与优化没有太大关系。
  • @M.M. const 告诉编译器对变量做出假设,这有助于在编译期间进行优化选择。但我可以承认,这不是它的主要目的。
  • @cdcdcd:恐怕您的声明仅适用于定义为const 限定的对象,不适用于定义为指向const 对象的指针。

标签: c gcc


【解决方案1】:

编译器没有理由假设函数f2 可能不会修改p 所指向的内容。 p 被定义为 const char *p 的事实只是告诉编译器 p 不能用于修改它指向的数据,而不是数据本身是常量。

如果你知道数组确实没有被函数f2()修改,你可以修改代码不再读取,看看gcc会不会做相应的优化:

int f1(const char *p) {
    char c = *p;
    if (!c)
        return 0;

    f2(); //not inlined

    if (c) { //should be always true
        //do something
        return 0;
    } else {
        //should be optimized out
        //do something else
        return 1;
    }
}

【讨论】:

  • 这可行,但这是我试图避免的解决方案。我想要的东西比每次我想要这种行为时都创建数据的本地副本更自动化
  • @gcc-question:您是否尝试将定义更改为int f1(const char * restrict p)
【解决方案2】:

您是否对构建进行了反汇编以确保它是正确的?尝试使用 restrict 关键字和 const 以确保编译器知道没有其他东西可以改变它;您正在调用另一个函数f2(),编译器无法知道在f2 中是否有另一个指向同一内存块的指针。但只有在此分支中没有任何内容修改同一块内存时才这样做。

如果 p 已初始化为 NULL,您的 if(!p[0]) 似乎很危险 - 没有什么可以取消引用。

【讨论】:

  • const 在这里无关紧要,但 restrict 可能会完成这项工作。 restrict 的精确语义是如此模糊,我不确定它是否应该。
  • @chqrlie au contraire...restrict 是少数具有精确数学规范的事物之一,因此我们最终不会争论词语的意图
  • 两者都可以。它可以同时被精确定义并不广为人知。
  • @M.M:我不假装没有,我只是说恕我直言,语义很难理解。例如,我不明白在函数声明中使用 restrict 限定指针参数意味着什么,就像标准头文件中的情况一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-12
  • 2021-06-10
  • 2017-12-24
  • 1970-01-01
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多