LLVM 24.0.0git
SLPMemoryUtils.cpp
Go to the documentation of this file.
1//===- SLPMemoryUtils.cpp - SLP pointer/stride helpers --------------------===//
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#include "SLPMemoryUtils.h"
11#include "SLPUtils.h"
12
13#include "llvm/ADT/STLExtras.h"
17#include "llvm/IR/DataLayout.h"
19
20#include <algorithm>
21#include <set>
22#include <utility>
23
24using namespace llvm;
25
26namespace llvm::slpvectorizer {
27
29 const TargetLibraryInfo &TLI, unsigned MaxDepth,
30 bool CompareOpcodes) {
31 if (getUnderlyingObject(Ptr1, MaxDepth) !=
32 getUnderlyingObject(Ptr2, MaxDepth))
33 return false;
34 auto *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
35 auto *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
36 return (!GEP1 || GEP1->getNumOperands() == 2) &&
37 (!GEP2 || GEP2->getNumOperands() == 2) &&
38 (((!GEP1 || isConstant(GEP1->getOperand(1))) &&
39 (!GEP2 || isConstant(GEP2->getOperand(1)))) ||
40 !CompareOpcodes ||
41 (GEP1 && GEP2 &&
42 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
43}
44
45/// Calculates minimal alignment as a common alignment.
47 Align CommonAlignment = cast<T>(VL.consume_front())->getAlign();
48 for (Value *V : VL)
49 CommonAlignment = std::min(CommonAlignment, cast<T>(V)->getAlign());
50 return CommonAlignment;
51}
52
55
56const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy,
57 const DataLayout &DL, ScalarEvolution &SE,
58 SmallVectorImpl<unsigned> &SortedIndices) {
60 const SCEV *PtrSCEVLowest = nullptr;
61 const SCEV *PtrSCEVHighest = nullptr;
62 // Find lower/upper pointers from the PointerOps (i.e. with lowest and highest
63 // addresses).
64 for (Value *Ptr : PointerOps) {
65 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
66 if (!PtrSCEV)
67 return nullptr;
68 SCEVs.push_back(PtrSCEV);
69 if (!PtrSCEVLowest && !PtrSCEVHighest) {
70 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
71 continue;
72 }
73 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
75 return nullptr;
76 if (Diff->isNonConstantNegative()) {
77 PtrSCEVLowest = PtrSCEV;
78 continue;
79 }
80 const SCEV *Diff1 = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEV);
81 if (isa<SCEVCouldNotCompute>(Diff1))
82 return nullptr;
83 if (Diff1->isNonConstantNegative()) {
84 PtrSCEVHighest = PtrSCEV;
85 continue;
86 }
87 }
88 // Dist = PtrSCEVHighest - PtrSCEVLowest;
89 const SCEV *Dist = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEVLowest);
91 return nullptr;
92 int Size = DL.getTypeStoreSize(ElemTy);
93 auto TryGetStride = [&](const SCEV *Dist,
94 const SCEV *Multiplier) -> const SCEV * {
95 if (const auto *M = dyn_cast<SCEVMulExpr>(Dist)) {
96 if (M->getOperand(0) == Multiplier)
97 return M->getOperand(1);
98 if (M->getOperand(1) == Multiplier)
99 return M->getOperand(0);
100 return nullptr;
101 }
102 if (Multiplier == Dist)
103 return SE.getConstant(Dist->getType(), 1);
104 return SE.getUDivExactExpr(Dist, Multiplier);
105 };
106 // Stride_in_elements = Dist / element_size * (num_elems - 1).
107 const SCEV *Stride = nullptr;
108 if (Size != 1 || SCEVs.size() > 1) {
109 const SCEV *Sz = SE.getConstant(Dist->getType(), Size * (SCEVs.size() - 1));
110 Stride = TryGetStride(Dist, Sz);
111 if (!Stride)
112 return nullptr;
113 }
114 if (!Stride || isa<SCEVConstant>(Stride))
115 return nullptr;
116 // Iterate through all pointers and check if all distances are
117 // unique multiple of Stride.
118 using DistOrdPair = std::pair<int64_t, int>;
119 auto Compare = llvm::less_first();
120 std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
121 bool IsConsecutive = true;
122 for (const auto [Idx, PtrSCEV] : enumerate(SCEVs)) {
123 unsigned Dist = 0;
124 if (PtrSCEV != PtrSCEVLowest) {
125 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
126 const SCEV *Coeff = TryGetStride(Diff, Stride);
127 if (!Coeff)
128 return nullptr;
129 const auto *SC = dyn_cast<SCEVConstant>(Coeff);
130 if (!SC || isa<SCEVCouldNotCompute>(SC))
131 return nullptr;
132 if (!SE.getMinusSCEV(PtrSCEV, SE.getAddExpr(PtrSCEVLowest,
133 SE.getMulExpr(Stride, SC)))
134 ->isZero())
135 return nullptr;
136 Dist = SC->getAPInt().getZExtValue();
137 }
138 // If the strides are not the same or repeated, we can't vectorize.
139 if ((Dist / Size) * Size != Dist || (Dist / Size) >= SCEVs.size())
140 return nullptr;
141 auto Res = Offsets.emplace(Dist, Idx);
142 if (!Res.second)
143 return nullptr;
144 // Consecutive order if the inserted element is the last one.
145 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
146 }
147 SortedIndices.clear();
148 if (!IsConsecutive) {
149 // Fill SortedIndices array only if it is non-consecutive.
150 SortedIndices.resize(PointerOps.size());
151 for (const auto [Idx, Pair] : enumerate(Offsets))
152 SortedIndices[Idx] = Pair.second;
153 }
154 return Stride;
155}
156
157} // namespace llvm::slpvectorizer
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static MaybeAlign getAlign(Value *Ptr)
This file contains some templates that are useful if you are working with the STL at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
Definition ArrayRef.h:156
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
This class represents an analyzed expression in the program.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI bool isNonConstantNegative() const
Return true if the specified scev is negated, but not a constant.
Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI const SCEV * getUDivExactExpr(SCEVUse LHS, SCEVUse RHS)
Get a canonical unsigned division expression, or something simpler if possible.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
A private "module" namespace for types and utilities used by this pass.
template Align computeCommonAlignment< StoreInst >(ArrayRef< Value * >)
Align computeCommonAlignment(ArrayRef< Value * > VL)
Calculates minimal alignment as a common alignment.
template Align computeCommonAlignment< LoadInst >(ArrayRef< Value * >)
const SCEV * calculateRtStride(ArrayRef< Value * > PointerOps, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< unsigned > &SortedIndices)
Checks if the provided list of pointers Pointers represents the strided pointers for type ElemTy.
InstructionsState getSameOpcode(ArrayRef< Value * > VL, const TargetLibraryInfo &TLI)
bool arePointersCompatible(Value *Ptr1, Value *Ptr2, const TargetLibraryInfo &TLI, unsigned MaxDepth, bool CompareOpcodes)
MaxDepth is the recursion limit for getUnderlyingObject.
bool isConstant(Value *V)
Definition SLPUtils.cpp:38
This is an optimization pass for GlobalISel generic memory operations.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1439