Search code examples
c++traitssimdc++20memory-alignment

Storing an std::assume_aligned pointer C++ 20


In C++ 20 we're getting assume aligned, this would be very usefull for audio code where pointers to aligned blocks of floats are passed around all the time. Let's say we have the following span type:

template<typename T>
struct Signal
{
    const T* data
    size_t size;
};

How would one indicate that the data pointer in this struct is aligned by some constexpr integer? Is something like this already possible in C++ 20?

constexpr int SIMDAlignment = 16;

template<typename T>
struct Signal
{
    aligned<SIMDAlignment> const T* data
    size_t size;
};

Solution

  • It seems that the assume-aligned hint is a property of a particular pointer object, and it cannot be made a property of a pointer type. However, you might try to wrap that pointer by an (inline) getter function and use std::assume_aligned for its return value. For example, in my experiment, when I used the pointer returned by such a function, it was treated as "aligned" (pointing to aligned data) correctly by GCC:

    double* f()
    {
      static double* data =
        (double*)std::aligned_alloc(64, 1024 * sizeof(double));
      return std::assume_aligned<64>(data);
    }
    
    void g()
    {
      double* a = f();
      for (int i = 0; i < 1024; i++)
        a[i] = 123.45;
    }
    

    In this case, the array was filled by vmovapd which requires aligned memory access.

    On the contrary, when I changed:

    return std::assume_aligned<64>(data);
    

    to:

    return data;
    

    The generated assembly contained vmovupd which works with unaligned data.

    Live demo: https://godbolt.org/z/d5aPPj — check the .L19 loop in both cases.