【问题标题】:Declaring a variable non-aliased in clang?在clang中声明一个无别名的变量?
【发布时间】:2016-12-26 13:55:35
【问题描述】:

有没有办法在clang 中声明一个变量是非别名的,以便在使用该变量的地方进行更多优化?

我了解restrict 可用于将指针声明为非别名。

但是,我也想知道可以指向的变量。我猜(也许是错误的)编译器必须小心假设可以允许它缓存变量值而不是每次都重新获取它的东西。

例子:

class Data
{   
public:
    void updateVal() {
        // Updates m_val with some value each time it's called (value may differ across different calls)
        ...
    }
    int complicatedCalculation() const {
        return 3 * m_val + 2;
    }
    int m_val;
};

class User
{
    User(Data& data) : m_data{data} {}
    void f()
    {
        m_data.updateVal();
        for (int i=0; i<1000; ++i)
            g();
    }
    void g()
    {
        // Will the optimizer be able to cache calc's value for use in all the calls to g() from f()?
        int calc = m_data.complicatedCalculation();

        // Do more work
        ...
    }

    Data& m_data;
};

即使示例代码中问题的答案是“是”,如果代码更复杂(例如工作在// Do more work 下),由于指针的可能性,它可能不会变为“否”指针可能指向m_data.m_val 的地方正在修改内容?或者这是编译器假设永远不会发生的事情,除非它看到 m_val 的地址被带到代码中的某个地方?

如果它假设,或者即使它假设,但m_val的地址确实被带到某个地方(但我们知道它的内容不会是修改),那么能够将m_val 标记为“安全”以消除别名问题会很好,因此可以假设它的值不会被指针访问更改。

【问题讨论】:

  • 您在寻找restrict 吗?
  • 好的,谢谢。不过,我也想知道非指针变量;将提供更多详细信息。
  • 添加了更多细节。
  • 为避免任何问题,您可以自己缓存calc 值,并将该值传递给gm_val可以通过修改int*Data*User*char*来修改。

标签: c++ clang compiler-optimization strict-aliasing


【解决方案1】:

编译器将分配一个寄存器来存储calcin g,除非它确定还有其他更热的变量可以更好地存储在寄存器中。

现在即使calc 存储在寄存器中,这仍可能需要对complicatedCalculation 的函数调用和对m_val 的内存访问。编译器可以内联complicatedCalculation 并消除函数调用,但它不能消除内存访问,除非它可以确定m_val 始终是一个有效的常量。

您真正想要的是在f 而不是g 的循环中消除对m_val 的不必要的内存访问。为此,编译器必须认为g 有资格在f 中内联。只有当它被内联时,编译器才能消除不必要的内存访问。即使g直接修改了m_val,编译器仍然可以在一个寄存器中分配calc并进行相应的修改。这里唯一需要注意的是g 可能 抛出异常。如果曾经抛出异常,则必须在允许传播异常之前将内存中的 m_val 版本更新为最新值。编译器必须发出代码来确保这一点。如果没有此代码,它必须在每次迭代中更新m_val 的内存版本。我不知道哪个版本的clang使用了哪种方法。您必须检查生成的汇编代码。

如果m_value 的地址在代码中的任何位置使用,编译器可能无法消除对它的任何内存访问。在这种情况下,使用restrict 可能会有所帮助。 m_value 不应通过任何其他指针进行修改,因为这违反了标准并导致未定义的行为。您有责任确保这一点。

我希望您关心这一点,因为您已经通过实验确定这是代码中的性能瓶颈,或者您只是出于好奇,而不是出于任何其他原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-04
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-30
    相关资源
    最近更新 更多