[llvm] [LoopVectorize][LAA] Hoist load in memory IV to allow vectorization (PR #168312)

Felipe Magno de Almeida via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 10 17:05:46 PST 2025


felipealmeida wrote:

Hello Florian,

[snip]

> Would it be possible to share a build-able reproducer? From looking at the code, I am surprised that we are not able to determine no-alias via TBAA metadata given that it looks like we are accessing 16 and 64 bit integers, which should be have different TBAA nodes.

So, SPEC 2017 is using -fno-strict-alising, which bypasses TBAAs.

Below is one that I was able to get together that reproduces it.

```
#include <cstdlib>
#include <algorithm>
struct MemoryManager
{
  void* allocate(size_t size);
};
template <class C>
struct MyConstructWithNoMemoryManager
{
  static C* construct(C* address, MemoryManager& /* mgr */)
  {
    return (C*) new (address) C;
  }
  static C* construct(C* address, const C& theRhs, MemoryManager& /* mgr */)
  {
    return (C*) new (address) C(theRhs);
  }
};
template <class C>
struct MyMemoryManagedConstructionTraits
{
  typedef MyConstructWithNoMemoryManager<C> Constructor;
};
template <class Type, class ConstructionTraits = MyMemoryManagedConstructionTraits<Type> >
struct MyXalanVector
{
  typedef Type                value_type;
  typedef value_type*         pointer;
  typedef const value_type*   const_pointer;
  typedef value_type&         reference;
  typedef const value_type&   const_reference;
  typedef std::size_t              size_type;
  typedef std::ptrdiff_t           difference_type;
  typedef value_type*             iterator;
  typedef const value_type*       const_iterator;
  typedef MyXalanVector<value_type, ConstructionTraits>     ThisType;
  typedef typename ConstructionTraits::Constructor    Constructor;
  MyXalanVector(
                MemoryManager&  theManager ,
                size_type           initialAllocation = size_type(0));
  MyXalanVector(
                const ThisType&     theSource,
                MemoryManager&      theManager ,
                size_type           theInitialAllocation = size_type(0)) :
    m_memoryManager(&theManager),
    m_size(0),
    m_allocation(0),
    m_data(0)
  {
    if (theSource.m_size > 0) {
      ThisType    theTemp(theManager, local_max(theSource.m_size, theInitialAllocation));
      theTemp.insert(theTemp.begin(), theSource.begin(), theSource.end());
      swap(theTemp);
    }
    else if (theInitialAllocation > 0) {
      m_data = allocate(theInitialAllocation);
      m_allocation = theInitialAllocation;
    }
  }
  
  value_type*
  allocate(size_type  size);
  void
  insert(
         iterator            thePosition,
         size_type           theCount,
         const value_type&   theData) ;
  pointer
  ensureCapacity(size_type    theSize);
  void
  insert(
         iterator        thePosition,
         const_iterator  theFirst,
         const_iterator  theLast)
  {
    const size_type     theInsertSize =
      std::distance(theFirst, theLast);
    if (theInsertSize == 0) return;
    const size_type     theTotalSize = size() + theInsertSize;
    if (thePosition == end()) {
      pointer     thePointer = ensureCapacity(theTotalSize);
      while (theFirst != theLast) {
        Constructor::construct(thePointer, *theFirst, *m_memoryManager);
        ++thePointer;
        ++m_size;
        ++theFirst;
      }
    } else {
      if (theTotalSize > capacity()) {
        ThisType    theTemp(*m_memoryManager, theTotalSize);
        theTemp.insert(theTemp.end(), begin(), thePosition);
        theTemp.insert(theTemp.end(), theFirst, theLast);
        theTemp.insert(theTemp.end(), thePosition, end());
        swap(theTemp);
      } else {
        const iterator      theOriginalEnd = end();
        const size_type     theRightSplitSize =
          std::distance(thePosition, theOriginalEnd);
        if (theRightSplitSize <= theInsertSize) {
          const const_iterator    toInsertSplit = theFirst + theRightSplitSize;
          const_iterator          toInsertIter = toInsertSplit;
          while (toInsertIter != theLast) {
            doPushBack(*toInsertIter);
            ++toInsertIter;
          }
          toInsertIter = thePosition;
          while (toInsertIter !=  theOriginalEnd) {
            doPushBack(*toInsertIter);
            ++toInsertIter;
          }
          std:: copy(theFirst, toInsertSplit, thePosition);
        } else {
          const_iterator  toMoveIter = end() - theInsertSize;
          while (toMoveIter != theOriginalEnd) {
            doPushBack(*toMoveIter);
            ++toMoveIter;
          }
          std:: copy_backward(thePosition, theOriginalEnd - theInsertSize, theOriginalEnd);
          std:: copy(theFirst, theLast, thePosition);
        }
      }
    }
  }
  size_type size() const;
  iterator begin();
  const_iterator begin() const;
  iterator end();
  const_iterator end() const;
  pointer endPointer();
  const_pointer endPointer() const;
  size_type capacity() const;
  void doPushBack(const value_type&   data);
  void doReserve(size_type     theSize);
  size_type local_max(size_type   theLHS, size_type theRHS);
  void swap(ThisType& theOther);
  MemoryManager*  m_memoryManager;
  size_type           m_size;
  size_type           m_allocation;
  value_type*         m_data;
};
typedef MyXalanVector<unsigned short> vector;
vector & foo1();
size_t theTotalSize();
void foobar()
{
  vector & self = foo1();
  vector theTemp(self, *self.m_memoryManager, theTotalSize());
}
```

I'm compiling using this: `clang++  -std=c++11 --target=aarch64-linux-gnu -c -o ElemAttribute.o -O3 -fno-strict-aliasing  ElemAttribute.cpp`


https://github.com/llvm/llvm-project/pull/168312


More information about the llvm-commits mailing list