blob: 42f5122a88041b00515d7ca61ce50ddad4355f3f [file]
//===- SLPMemoryUtils.h - SLP pointer/stride helpers -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Internal header used by SLPVectorizer.cpp. It declares free pointer and
// stride helpers that do not depend on BoUpSLP or any other SLP-private type.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H
#define LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Support/Alignment.h"
namespace llvm {
class AssumptionCache;
class BasicBlock;
class ConstantInt;
class DataLayout;
class DominatorTree;
class FixedVectorType;
class SCEV;
class ScalarEvolution;
class TargetLibraryInfo;
class Type;
class Value;
class VectorType;
} // namespace llvm
namespace llvm::slpvectorizer {
/// \p MaxDepth is the recursion limit for getUnderlyingObject.
bool arePointersCompatible(Value *Ptr1, Value *Ptr2,
const TargetLibraryInfo &TLI, unsigned MaxDepth,
bool CompareOpcodes = true);
/// Returns \p Stride scaled by the allocation size of \p ScalarTy, negated if
/// \p IsReverse is set, or nullptr if \p Stride is not a constant.
ConstantInt *getStrideBytesIfConstant(Value *Stride, Type *ScalarTy,
const DataLayout &DL,
bool IsReverse = false);
/// Calculates minimal alignment as a common alignment.
template <typename T> Align computeCommonAlignment(ArrayRef<Value *> VL);
/// Checks if the provided list of pointers \p Pointers represents the strided
/// pointers for type ElemTy. If they are not, nullptr is returned.
/// Otherwise, SCEV* of the stride value is returned.
/// If `PointerOps` can be rearranged into the following sequence:
/// ```
/// %x + c_0 * stride,
/// %x + c_1 * stride,
/// %x + c_2 * stride
/// ...
/// ```
/// where each `c_i` is constant. The SCEV of the `stride` will be returned.
const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy,
const DataLayout &DL, ScalarEvolution &SE,
SmallVectorImpl<unsigned> &SortedIndices);
/// Checks if the \p VL can be transformed to a (masked)load + compress or
/// (masked) interleaved load.
bool isMaskedLoadCompress(
ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
ArrayRef<unsigned> Order, const TargetTransformInfo &TTI,
const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC,
const DominatorTree &DT, const TargetLibraryInfo &TLI,
const TargetTransformInfo::TargetCostKind CostKind,
const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec,
bool &IsMasked, unsigned &InterleaveFactor,
SmallVectorImpl<int> &CompressMask, VectorType *&LoadVecTy);
/// Checks if the \p VL can be transformed to a (masked)load + compress or
/// (masked) interleaved load.
bool isMaskedLoadCompress(
ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
ArrayRef<unsigned> Order, const TargetTransformInfo &TTI,
const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC,
const DominatorTree &DT, const TargetLibraryInfo &TLI,
const TargetTransformInfo::TargetCostKind CostKind,
const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec);
/// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a
/// single masked store. On success \p StoreVecTy is the widened store type and
/// \p ReuseShuffleIndices is the expand mask that places each stored value at
/// its element offset from the base (poison in the gaps).
bool isMaskedStoreCompress(ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
ArrayRef<unsigned> Order,
const TargetTransformInfo &TTI, const DataLayout &DL,
ScalarEvolution &SE, Align CommonAlignment,
SmallVectorImpl<int> &ReuseShuffleIndices,
FixedVectorType *&StoreVecTy);
/// Clusters \p VL pointers by (basic block, underlying object) pair and sorts
/// each cluster by offset. Returns false and leaves \p SortedIndices empty if
/// the accesses are not worth reordering.
bool clusterSortPtrAccesses(ArrayRef<Value *> VL, ArrayRef<BasicBlock *> BBs,
Type *ElemTy, const DataLayout &DL,
ScalarEvolution &SE, unsigned MaxDepth,
SmallVectorImpl<unsigned> &SortedIndices);
} // namespace llvm::slpvectorizer
#endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H