Multiplication with DiagonalMatrix leads to heap allocation

Summary

When multiplying a DiagonalMatrix with a Matrix, a heap allocation occurs:

// Arr_Ru <-- MatrixXd
// Ru <-- MatrixXd
// Arr <-- DiagonalMatrix<double>
Arr_Ru.noalias() = Arr * Ru; // alloc here
Arr_Ru.noalias() = Arr.diagonal().asDiagonal() * Ru;  // no alloc here

Environment

  • Operating System : Linux
  • Architecture : x64
  • Eigen Version : 3.3.7 and 3.4.0
  • Compiler Version : Clang12, Gcc9
  • Compile Flags : none as well as -O3 -march=native
  • Vector Extension : EIGEN_DONT_VECTORIZE as well as "standard flags"

Minimal Example

Minimal example with Eigen 3.4.0: https://godbolt.org/z/dvWWEza8f

#define EIGEN_RUNTIME_NO_MALLOC // Define this symbol to enable runtime tests for allocations

#include <iostream>
#include <Eigen/Core>

constexpr int N = 76;    // issue independent of size
constexpr int NBT = 10;  // deliberately small for godbolt

int main() {
    Eigen::internal::set_is_malloc_allowed(true);
    Eigen::MatrixXd Arr_Ru = Eigen::MatrixXd::Zero(N, N);
    Eigen::MatrixXd Ru = Eigen::MatrixXd::Random(N, N);
    Eigen::DiagonalMatrix<double, -1, -1> Arr(N); Arr.setIdentity();

    Eigen::internal::set_is_malloc_allowed(false);

    for (std::size_t i = 0; i < NBT; ++i)
    {
        Arr_Ru.noalias() = Arr * Ru; // alloc here
        //Arr_Ru.noalias() = Arr.diagonal().asDiagonal() * Ru;  // no alloc here [workaround]
    }

    return 0;
}

What is the current bug behavior?

Heap allocation

What is the expected correct behavior?

Allocation-free