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
22namespace llvm {
23class AssumptionCache;
24class BasicBlock;
25class ConstantInt;
26class DataLayout;
27class DominatorTree;
28class FixedVectorType;
29class IRBuilderBase;
30class SCEV;
31class ScalarEvolution;
32class TargetLibraryInfo;
33class Type;
34class Value;
35class VectorType;
36} // namespace llvm
37
38namespace llvm::slpvectorizer {
39
40/// \p MaxDepth is the recursion limit for getUnderlyingObject.
41bool 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.
47ConstantInt *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.
53Value *createWidenedStridedCast(IRBuilderBase &Builder, Value *V, Type *DstTy,
54 const DataLayout &DL);
55
56/// Calculates minimal alignment as a common alignment.
57template <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.
70const 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.
76bool 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.
88bool 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).
100bool 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.
110bool 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