| 1 | //===- SLPMemoryUtils.h - SLP pointer/stride helpers -----------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // Internal header used by SLPVectorizer.cpp. It declares free pointer and |
| 10 | // stride helpers that do not depend on BoUpSLP or any other SLP-private type. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H |
| 15 | #define LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H |
| 16 | |
| 17 | #include "llvm/ADT/ArrayRef.h" |
| 18 | #include "llvm/ADT/STLFunctionalExtras.h" |
| 19 | #include "llvm/Analysis/TargetTransformInfo.h" |
| 20 | #include "llvm/Support/Alignment.h" |
| 21 | |
| 22 | namespace llvm { |
| 23 | class AssumptionCache; |
| 24 | class BasicBlock; |
| 25 | class ConstantInt; |
| 26 | class DataLayout; |
| 27 | class DominatorTree; |
| 28 | class FixedVectorType; |
| 29 | class IRBuilderBase; |
| 30 | class SCEV; |
| 31 | class ScalarEvolution; |
| 32 | class TargetLibraryInfo; |
| 33 | class Type; |
| 34 | class Value; |
| 35 | class VectorType; |
| 36 | } // namespace llvm |
| 37 | |
| 38 | namespace llvm::slpvectorizer { |
| 39 | |
| 40 | /// \p MaxDepth is the recursion limit for getUnderlyingObject. |
| 41 | bool arePointersCompatible(Value *Ptr1, Value *Ptr2, |
| 42 | const TargetLibraryInfo &TLI, unsigned MaxDepth, |
| 43 | bool CompareOpcodes = true); |
| 44 | |
| 45 | /// Returns \p Stride scaled by the allocation size of \p ScalarTy, negated if |
| 46 | /// \p IsReverse is set, or nullptr if \p Stride is not a constant. |
| 47 | ConstantInt *getStrideBytesIfConstant(Value *Stride, Type *ScalarTy, |
| 48 | const DataLayout &DL, |
| 49 | bool IsReverse = false); |
| 50 | |
| 51 | /// Casts \p V between the widened strided access type and the entry vector |
| 52 | /// type \p DstTy. |
| 53 | Value *createWidenedStridedCast(IRBuilderBase &Builder, Value *V, Type *DstTy, |
| 54 | const DataLayout &DL); |
| 55 | |
| 56 | /// Calculates minimal alignment as a common alignment. |
| 57 | template <typename T> Align computeCommonAlignment(ArrayRef<Value *> VL); |
| 58 | |
| 59 | /// Checks if the provided list of pointers \p Pointers represents the strided |
| 60 | /// pointers for type ElemTy. If they are not, nullptr is returned. |
| 61 | /// Otherwise, SCEV* of the stride value is returned. |
| 62 | /// If `PointerOps` can be rearranged into the following sequence: |
| 63 | /// ``` |
| 64 | /// %x + c_0 * stride, |
| 65 | /// %x + c_1 * stride, |
| 66 | /// %x + c_2 * stride |
| 67 | /// ... |
| 68 | /// ``` |
| 69 | /// where each `c_i` is constant. The SCEV of the `stride` will be returned. |
| 70 | const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy, |
| 71 | const DataLayout &DL, ScalarEvolution &SE, |
| 72 | SmallVectorImpl<unsigned> &SortedIndices); |
| 73 | |
| 74 | /// Checks if the \p VL can be transformed to a (masked)load + compress or |
| 75 | /// (masked) interleaved load. |
| 76 | bool isMaskedLoadCompress( |
| 77 | ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps, |
| 78 | ArrayRef<unsigned> Order, const TargetTransformInfo &TTI, |
| 79 | const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC, |
| 80 | const DominatorTree &DT, const TargetLibraryInfo &TLI, |
| 81 | const TargetTransformInfo::TargetCostKind CostKind, |
| 82 | const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec, |
| 83 | bool &IsMasked, unsigned &InterleaveFactor, |
| 84 | SmallVectorImpl<int> &CompressMask, VectorType *&LoadVecTy); |
| 85 | |
| 86 | /// Checks if the \p VL can be transformed to a (masked)load + compress or |
| 87 | /// (masked) interleaved load. |
| 88 | bool isMaskedLoadCompress( |
| 89 | ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps, |
| 90 | ArrayRef<unsigned> Order, const TargetTransformInfo &TTI, |
| 91 | const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC, |
| 92 | const DominatorTree &DT, const TargetLibraryInfo &TLI, |
| 93 | const TargetTransformInfo::TargetCostKind CostKind, |
| 94 | const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec); |
| 95 | |
| 96 | /// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a |
| 97 | /// single masked store. On success \p StoreVecTy is the widened store type and |
| 98 | /// \p ReuseShuffleIndices is the expand mask that places each stored value at |
| 99 | /// its element offset from the base (poison in the gaps). |
| 100 | bool isMaskedStoreCompress(ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps, |
| 101 | ArrayRef<unsigned> Order, |
| 102 | const TargetTransformInfo &TTI, const DataLayout &DL, |
| 103 | ScalarEvolution &SE, Align CommonAlignment, |
| 104 | SmallVectorImpl<int> &ReuseShuffleIndices, |
| 105 | FixedVectorType *&StoreVecTy); |
| 106 | |
| 107 | /// Clusters \p VL pointers by (basic block, underlying object) pair and sorts |
| 108 | /// each cluster by offset. Returns false and leaves \p SortedIndices empty if |
| 109 | /// the accesses are not worth reordering. |
| 110 | bool clusterSortPtrAccesses(ArrayRef<Value *> VL, ArrayRef<BasicBlock *> BBs, |
| 111 | Type *ElemTy, const DataLayout &DL, |
| 112 | ScalarEvolution &SE, unsigned MaxDepth, |
| 113 | SmallVectorImpl<unsigned> &SortedIndices); |
| 114 | |
| 115 | } // namespace llvm::slpvectorizer |
| 116 | |
| 117 | #endif // LLVM_LIB_TRANSFORMS_VECTORIZE_SLPVECTORIZER_SLPMEMORYUTILS_H |
| 118 | |