![]() ![]() It also bears mentioning that calls to ‘rows’ and ‘cols’ are inline-expanded as well, even though those are on a statically dead path. This eats into both the optimizer throughput as well as the inliner’s code-size budget. To realize this win though the compiler must fully evaluate and expand outerStride’s 18 total callees, for every callsite of outerStride in the module. Therefore, it is an excellent candidate for full inline expansion. That instantiation of outerStride does nothing but return one of its members. : int(IsRowMajor) ? this->cols() : this->rows() Return IsVectorAtCompileTime ? this->size() Which calls innerSize: template class DenseBase Consider the following routine in the Eigen library: Eigen::Matrix::outerStride(void) Unfortunately, many of the coding patterns and idioms common to heavy generic programming bump into those constraints. The inliner’s view of the world is always «pre-optimized.» It has very limited knowledge of copy propagation and dead control paths for example.It has the difficult job of balancing executable size with runtime performance. Inline decisions are context sensitive and it is not always profitable to replay its decision-making for the same function. The inliner is recursive and may often re-do work it has already done.Terry Mahaffey has provided an overview of Visual Studio’s inlining decisions. This details some of the inliner’s constraints and areas for improvement, a few of which are particularly relevant here:
0 Comments
Leave a Reply. |