为何GCC -O2无法对传递Eigen表达式的递归函数做尾调用优化
尾调用优化失效原因分析
- 首先GCC触发尾调用优化(TCO)的核心前提是:当前函数栈帧可以被下一层调用完全复用,不需要保留任何待执行的清理逻辑。你给出的double版本代码中所有参数、返回值都是平凡类型,构造、析构没有任何副作用,满足复用条件,因此-O2级别下可以正常完成优化。
- 你使用的
Eigen::MatrixXd、Eigen::VectorXd是动态尺寸类型,内部持有堆分配的内存缓冲区,属于非平凡析构类型:当前递归层生成的临时向量(比如A.ldlt().solve(b)或者它的eval()返回值)的析构必须在当前栈帧退出前执行,编译器无法直接丢弃当前栈帧跳转到下一层递归,自然无法完成栈帧复用。 - 递归调用的第二个参数传入的是临时对象,该临时对象的生命周期绑定到当前递归层的调用表达式,编译器需要保证递归调用返回后正确销毁该临时,这个额外的清理逻辑也会阻碍TCO触发。
- 即便你改用固定大小的栈上Eigen类型(比如
Eigen::Matrix<double,2,2>、Eigen::Vector<double,2>),也要确认求解逻辑没有无法被优化掉的内部副作用,否则依然可能无法触发TCO。
内容的提问来源于stack exchange,提问作者Anon232
相关产品推荐
相关产品推荐

