Pass-by-reference hinders gcc from tail call elimination

拜拜、爱过 提交于 2019-12-05 04:46:06
Orest Hera

As it is noted by @jxh the cast static_cast<int>() creates a temporary whose reference is passed to the print function. Without such cast the tail recursion is optimized correctly.

The issue is very similar to the old case Why isn't g++ tail call optimizing while gcc is? and the workaround may be similar to https://stackoverflow.com/a/31793391/4023446.

It is still possible to use System with the arguments passed by reference if call to System::print will be moved to a separate private helper function SystemPrint:

class BlendingTable : public Array<unsigned char, 3> {

//...

private:
    void SystemPrint(int dst, int src, int a) const
    {
        System::print(static_cast<int>((*this)(FF - dst, FF - src, FF - a)), ' ');
    }

    void print(int dst, int src, int a) const {
        SystemPrint(dst, src, a);
        if (a > 0) {
            print(dst, src, a - 1);
        } else if (src > 0) {
            print(dst, src - 1, FF);
        } else if (dst > 0) {
            print(dst - 1, FF, FF);
        } else {
            System::printLine();
            return;
        }
    }

// ...

}

Now the tail call optimization works (g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2 with the optimization option -O2) and the print does not cause a stack overflow.

Update

I verified it with other compilers:

  • the original code without any change is perfectly optimized by clang++ Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) with -O1 optimization
  • g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 fails to perform TCO even without the cast or with the wrapping function SystemPrint workaround; here only the workaround with System::print arguments by values works.

So, the issue is very specific to compiler versions.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!