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 "SLPCostAnalysis.h"
12#include "SLPTypeUtils.h"
13#include "SLPUtils.h"
14
15#include "llvm/ADT/APInt.h"
16#include "llvm/ADT/MapVector.h"
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/Sequence.h"
20#include "llvm/Analysis/Loads.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/DataLayout.h"
30#include "llvm/IR/Intrinsics.h"
32
33#include <algorithm>
34#include <limits>
35#include <optional>
36#include <set>
37#include <tuple>
38#include <utility>
39
40using namespace llvm;
41
42namespace llvm::slpvectorizer {
43
45 const DataLayout &DL, bool IsReverse) {
46 auto *CI = dyn_cast_or_null<ConstantInt>(Stride);
47 if (!CI)
48 return nullptr;
49
50 uint64_t ElementSize = DL.getTypeAllocSize(ScalarTy).getFixedValue();
51 APInt Bytes = CI->getValue() * ElementSize;
52 return ConstantInt::get(CI->getContext(), IsReverse ? -Bytes : Bytes);
53}
54
56 const TargetLibraryInfo &TLI, unsigned MaxDepth,
57 bool CompareOpcodes) {
58 if (getUnderlyingObject(Ptr1, MaxDepth) !=
59 getUnderlyingObject(Ptr2, MaxDepth))
60 return false;
61 auto *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
62 auto *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
63 return (!GEP1 || GEP1->getNumOperands() == 2) &&
64 (!GEP2 || GEP2->getNumOperands() == 2) &&
65 (((!GEP1 || isConstant(GEP1->getOperand(1))) &&
66 (!GEP2 || isConstant(GEP2->getOperand(1)))) ||
67 !CompareOpcodes ||
68 (GEP1 && GEP2 &&
69 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
70}
71
72/// Calculates minimal alignment as a common alignment.
74 Align CommonAlignment = cast<T>(VL.consume_front())->getAlign();
75 for (Value *V : VL)
76 CommonAlignment = std::min(CommonAlignment, cast<T>(V)->getAlign());
77 return CommonAlignment;
78}
79
82
84 const DataLayout &DL, ScalarEvolution &SE,
85 SmallVectorImpl<unsigned> &SortedIndices) {
87 const SCEV *PtrSCEVLowest = nullptr;
88 const SCEV *PtrSCEVHighest = nullptr;
89 // Find lower/upper pointers from the PointerOps (i.e. with lowest and highest
90 // addresses).
91 for (Value *Ptr : PointerOps) {
92 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
93 if (!PtrSCEV)
94 return nullptr;
95 SCEVs.push_back(PtrSCEV);
96 if (!PtrSCEVLowest && !PtrSCEVHighest) {
97 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
98 continue;
99 }
100 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
101 if (isa<SCEVCouldNotCompute>(Diff))
102 return nullptr;
103 if (Diff->isNonConstantNegative()) {
104 PtrSCEVLowest = PtrSCEV;
105 continue;
106 }
107 const SCEV *Diff1 = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEV);
108 if (isa<SCEVCouldNotCompute>(Diff1))
109 return nullptr;
110 if (Diff1->isNonConstantNegative()) {
111 PtrSCEVHighest = PtrSCEV;
112 continue;
113 }
114 }
115 // Dist = PtrSCEVHighest - PtrSCEVLowest;
116 const SCEV *Dist = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEVLowest);
117 if (isa<SCEVCouldNotCompute>(Dist))
118 return nullptr;
119 int Size = DL.getTypeStoreSize(ElemTy);
120 auto TryGetStride = [&](const SCEV *Dist,
121 const SCEV *Multiplier) -> const SCEV * {
122 if (const auto *M = dyn_cast<SCEVMulExpr>(Dist)) {
123 if (M->getOperand(0) == Multiplier)
124 return M->getOperand(1);
125 if (M->getOperand(1) == Multiplier)
126 return M->getOperand(0);
127 return nullptr;
128 }
129 if (Multiplier == Dist)
130 return SE.getConstant(Dist->getType(), 1);
131 return SE.getUDivExactExpr(Dist, Multiplier);
132 };
133 // Stride_in_elements = Dist / element_size * (num_elems - 1).
134 const SCEV *Stride = nullptr;
135 if (Size != 1 || SCEVs.size() > 1) {
136 const SCEV *Sz = SE.getConstant(Dist->getType(), Size * (SCEVs.size() - 1));
137 Stride = TryGetStride(Dist, Sz);
138 if (!Stride)
139 return nullptr;
140 }
141 if (!Stride || isa<SCEVConstant>(Stride))
142 return nullptr;
143 // Iterate through all pointers and check if all distances are
144 // unique multiple of Stride.
145 using DistOrdPair = std::pair<int64_t, int>;
146 auto Compare = llvm::less_first();
147 std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
148 bool IsConsecutive = true;
149 for (const auto [Idx, PtrSCEV] : enumerate(SCEVs)) {
150 unsigned Dist = 0;
151 if (PtrSCEV != PtrSCEVLowest) {
152 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
153 const SCEV *Coeff = TryGetStride(Diff, Stride);
154 if (!Coeff)
155 return nullptr;
156 const auto *SC = dyn_cast<SCEVConstant>(Coeff);
157 if (!SC || isa<SCEVCouldNotCompute>(SC))
158 return nullptr;
159 if (!SE.getMinusSCEV(PtrSCEV, SE.getAddExpr(PtrSCEVLowest,
160 SE.getMulExpr(Stride, SC)))
161 ->isZero())
162 return nullptr;
163 Dist = SC->getAPInt().getZExtValue();
164 }
165 // If the strides are not the same or repeated, we can't vectorize.
166 if ((Dist / Size) * Size != Dist || (Dist / Size) >= SCEVs.size())
167 return nullptr;
168 auto Res = Offsets.emplace(Dist, Idx);
169 if (!Res.second)
170 return nullptr;
171 // Consecutive order if the inserted element is the last one.
172 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
173 }
174 SortedIndices.clear();
175 if (!IsConsecutive) {
176 // Fill SortedIndices array only if it is non-consecutive.
177 SortedIndices.resize(PointerOps.size());
178 for (const auto [Idx, Pair] : enumerate(Offsets))
179 SortedIndices[Idx] = Pair.second;
180 }
181 return Stride;
182}
183
184/// Builds compress-like mask for shuffles for the given \p PointerOps, ordered
185/// with \p Order.
186/// \return true if the mask represents strided access, false - otherwise.
188 ArrayRef<unsigned> Order, Type *ScalarTy,
189 const DataLayout &DL, ScalarEvolution &SE,
190 SmallVectorImpl<int> &CompressMask) {
191 const unsigned Sz = PointerOps.size();
192 CompressMask.assign(Sz, PoisonMaskElem);
193 // The first element always set.
194 CompressMask[0] = 0;
195 // Check if the mask represents strided access.
196 std::optional<unsigned> Stride = 0;
197 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
198 for (unsigned I : seq<unsigned>(1, Sz)) {
199 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
200 std::optional<int64_t> OptPos =
201 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
202 if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
203 return false;
204 unsigned Pos = static_cast<unsigned>(*OptPos);
205 CompressMask[I] = Pos;
206 if (!Stride)
207 continue;
208 if (*Stride == 0) {
209 *Stride = Pos;
210 continue;
211 }
212 if (Pos != *Stride * I)
213 Stride.reset();
214 }
215 return Stride.has_value();
216}
217
218/// Checks if the \p VL can be transformed to a (masked)load + compress or
219/// (masked) interleaved load.
224 const DominatorTree &DT, const TargetLibraryInfo &TLI,
226 const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec,
227 bool &IsMasked, unsigned &InterleaveFactor,
228 SmallVectorImpl<int> &CompressMask, VectorType *&LoadVecTy) {
229 InterleaveFactor = 0;
230 Type *ScalarTy = VL.front()->getType();
231 const size_t Sz = VL.size();
232 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, Sz));
233 SmallVector<int> Mask;
234 if (!Order.empty())
235 inversePermutation(Order, Mask);
236 // Check external uses.
237 for (const auto [I, V] : enumerate(VL)) {
238 if (AreAllUsersVectorized(V))
239 continue;
240 InstructionCost ExtractCost =
241 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
242 Mask.empty() ? I : Mask[I]);
243 InstructionCost ScalarCost =
244 TTI.getInstructionCost(cast<Instruction>(V), CostKind);
245 if (ExtractCost <= ScalarCost)
246 return false;
247 }
248 Value *Ptr0;
249 Value *PtrN;
250 if (Order.empty()) {
251 Ptr0 = PointerOps.front();
252 PtrN = PointerOps.back();
253 } else {
254 Ptr0 = PointerOps[Order.front()];
255 PtrN = PointerOps[Order.back()];
256 }
257 std::optional<int64_t> Diff =
258 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
259 if (!Diff)
260 return false;
261 const size_t MaxRegSize =
263 .getFixedValue();
264 // Check for very large distances between elements.
265 if (*Diff / Sz >= MaxRegSize / 8)
266 return false;
267 LoadVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
268 auto *LI = cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()]);
269 Align CommonAlignment = LI->getAlign();
270 SimplifyQuery SQ(
271 DL, &TLI, &DT, &AC,
272 cast<LoadInst>(Order.empty() ? VL.back() : VL[Order.back()]));
273 IsMasked = !isSafeToLoadUnconditionally(Ptr0, LoadVecTy, CommonAlignment, SQ);
274 if (IsMasked && !TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
275 LI->getPointerAddressSpace()))
276 return false;
277 // TODO: perform the analysis of each scalar load for better
278 // safe-load-unconditionally analysis.
279 bool IsStrided =
280 buildCompressMask(PointerOps, Order, ScalarTy, DL, SE, CompressMask);
281 assert(CompressMask.size() >= 2 && "At least two elements are required");
282 SmallVector<Value *> OrderedPointerOps(PointerOps);
283 if (!Order.empty())
284 reorderScalars(OrderedPointerOps, Mask);
285 auto [ScalarGEPCost, VectorGEPCost] =
286 getGEPCosts(TTI, OrderedPointerOps, OrderedPointerOps.front(),
287 Instruction::Load, CostKind, ScalarTy, LoadVecTy);
288 // The cost of scalar loads.
289 InstructionCost ScalarLoadsCost =
291 [&](InstructionCost C, Value *V) {
292 return C + TTI.getInstructionCost(cast<Instruction>(V),
293 CostKind);
294 }) +
295 ScalarGEPCost;
296 APInt DemandedElts = APInt::getAllOnes(Sz);
297 InstructionCost GatherCost =
298 getScalarizationOverhead(TTI, ReVec, ScalarTy, VecTy, DemandedElts,
299 /*Insert=*/true,
300 /*Extract=*/false, CostKind) +
301 ScalarLoadsCost;
302 InstructionCost LoadCost = 0;
303 if (IsMasked) {
304 LoadCost = TTI.getMemIntrinsicInstrCost(
305 MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
306 CommonAlignment,
307 LI->getPointerAddressSpace()),
308 CostKind);
309 } else {
310 LoadCost =
311 TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
312 LI->getPointerAddressSpace(), CostKind,
313 TTI::getOperandInfo(LI->getPointerOperand()));
314 }
315 if (IsStrided && !IsMasked && Order.empty()) {
316 // Check for potential segmented(interleaved) loads.
317 VectorType *AlignedLoadVecTy = cast<VectorType>(getWidenedType(
318 ScalarTy,
319 getFullVectorNumberOfElements(TTI, ScalarTy, *Diff + 1, ReVec)));
320 SimplifyQuery SQ(DL, &TLI, &DT, &AC, cast<LoadInst>(VL.back()));
321 if (!isSafeToLoadUnconditionally(Ptr0, AlignedLoadVecTy, CommonAlignment,
322 SQ))
323 AlignedLoadVecTy = LoadVecTy;
324 if (TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
325 CommonAlignment,
326 LI->getPointerAddressSpace())) {
327 InstructionCost InterleavedCost =
328 VectorGEPCost + TTI.getInterleavedMemoryOpCost(
329 Instruction::Load, AlignedLoadVecTy,
330 CompressMask[1], {}, CommonAlignment,
331 LI->getPointerAddressSpace(), CostKind, IsMasked);
332 if (InterleavedCost < GatherCost) {
333 InterleaveFactor = CompressMask[1];
334 LoadVecTy = AlignedLoadVecTy;
335 return true;
336 }
337 }
338 }
339 // Estimating the compression shuffle cost below can be extremely expensive
340 // for a very wide LoadVecTy, which is split into a large number of vector
341 // registers (see processShuffleMasks). The shuffle cost is always
342 // non-negative, so if the load cost alone already reaches the gather cost the
343 // masked-load-compress cannot be profitable. Bail out before the costly
344 // shuffle cost estimation in that case.
345 if (VectorGEPCost + LoadCost >= GatherCost)
346 return false;
347 InstructionCost CompressCost = getShuffleCost(
348 TTI, TTI::SK_PermuteSingleSrc, LoadVecTy, CostKind, CompressMask);
349 if (!Order.empty()) {
350 SmallVector<int> NewMask(Sz, PoisonMaskElem);
351 for (unsigned I : seq<unsigned>(Sz)) {
352 NewMask[I] = CompressMask[Mask[I]];
353 }
354 CompressMask.swap(NewMask);
355 }
356 InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
357 return TotalVecCost < GatherCost;
358}
359
360/// Checks if the \p VL can be transformed to a (masked)load + compress or
361/// (masked) interleaved load.
366 const DominatorTree &DT, const TargetLibraryInfo &TLI,
368 const function_ref<bool(Value *)> AreAllUsersVectorized, bool ReVec) {
369 bool IsMasked;
370 unsigned InterleaveFactor;
371 SmallVector<int> CompressMask;
372 VectorType *LoadVecTy;
373 return isMaskedLoadCompress(VL, PointerOps, Order, TTI, DL, SE, AC, DT, TLI,
374 CostKind, AreAllUsersVectorized, ReVec, IsMasked,
375 InterleaveFactor, CompressMask, LoadVecTy);
376}
377
378/// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a
379/// single masked store. On success \p StoreVecTy is the widened store type and
380/// \p ReuseShuffleIndices is the expand mask that places each stored value at
381/// its element offset from the base (poison in the gaps).
383 ArrayRef<unsigned> Order,
384 const TargetTransformInfo &TTI, const DataLayout &DL,
385 ScalarEvolution &SE, Align CommonAlignment,
386 SmallVectorImpl<int> &ReuseShuffleIndices,
387 FixedVectorType *&StoreVecTy) {
388 Type *ScalarTy = cast<StoreInst>(VL.front())->getValueOperand()->getType();
389 const size_t Sz = VL.size();
390 // Only simple scalar element types are supported.
391 if (Sz < 2 || (!ScalarTy->isIntOrPtrTy() && !ScalarTy->isFloatingPointTy()))
392 return false;
393 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
394 Value *PtrN = Order.empty() ? PointerOps.back() : PointerOps[Order.back()];
395 std::optional<int64_t> Diff =
396 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
397 if (!Diff || *Diff <= 0)
398 return false;
399 // Avoid widened vectors with very large gaps between the stored elements.
400 const unsigned MaxRegSize =
402 .getFixedValue();
403 const unsigned ScalarBits = DL.getTypeSizeInBits(ScalarTy).getFixedValue();
404 if (ScalarBits == 0 ||
405 static_cast<uint64_t>(*Diff) / Sz >= MaxRegSize / ScalarBits)
406 return false;
407 StoreVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
408 unsigned AS = cast<StoreInst>(VL.front())->getPointerAddressSpace();
409 if (!TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
411 return false;
412 // Build the expand mask: store I (in address-sorted order) is placed at its
413 // element offset from the base, other widened lanes are poison.
414 ReuseShuffleIndices.assign(*Diff + 1, PoisonMaskElem);
415 int64_t Prev = -1;
416 for (unsigned I : seq<unsigned>(Sz)) {
417 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
418 std::optional<int64_t> Off =
419 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
420 if (!Off || *Off <= Prev || *Off > *Diff)
421 return false;
422 ReuseShuffleIndices[*Off] = static_cast<int>(I);
423 Prev = *Off;
424 }
425 return true;
426}
427
429 Type *ElemTy, const DataLayout &DL,
430 ScalarEvolution &SE, unsigned MaxDepth,
431 SmallVectorImpl<unsigned> &SortedIndices) {
432 assert(
433 all_of(VL, [](const Value *V) { return V->getType()->isPointerTy(); }) &&
434 "Expected list of pointer operands.");
435 // Map from bases to a vector of (Ptr, Offset, OrigIdx), which we insert each
436 // Ptr into, sort and return the sorted indices with values next to one
437 // another.
439 std::pair<BasicBlock *, Value *>,
441 Bases;
442 Bases
443 .try_emplace(std::make_pair(BBs.front(),
444 getUnderlyingObject(VL.front(), MaxDepth)))
445 .first->second.emplace_back()
446 .emplace_back(VL.front(), 0U, 0U);
447
448 SortedIndices.clear();
449 for (auto [Cnt, Ptr] : enumerate(VL.drop_front())) {
450 auto Key = std::make_pair(BBs[Cnt + 1], getUnderlyingObject(Ptr, MaxDepth));
451 bool Found = any_of(Bases.try_emplace(Key).first->second,
452 [&, &Cnt = Cnt, &Ptr = Ptr](auto &Base) {
453 std::optional<int64_t> Diff =
454 getPointersDiff(ElemTy, std::get<0>(Base.front()),
455 ElemTy, Ptr, DL, SE,
456 /*StrictCheck=*/true);
457 if (!Diff)
458 return false;
459
460 Base.emplace_back(Ptr, *Diff, Cnt + 1);
461 return true;
462 });
463
464 if (!Found) {
465 // If we haven't found enough to usefully cluster, return early.
466 if (Bases.size() > VL.size() / 2 - 1)
467 return false;
468
469 // Not found already - add a new Base
470 Bases.find(Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
471 }
472 }
473
474 if (Bases.size() == VL.size())
475 return false;
476
477 if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
478 Bases.front().second.size() == VL.size()))
479 return false;
480
481 // For each of the bases sort the pointers by Offset and check if any of the
482 // base become consecutively allocated.
483 auto ComparePointers = [MaxDepth](Value *Ptr1, Value *Ptr2) {
484 SmallPtrSet<Value *, 13> FirstPointers;
485 SmallPtrSet<Value *, 13> SecondPointers;
486 Value *P1 = Ptr1;
487 Value *P2 = Ptr2;
488 unsigned Depth = 0;
489 while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1)) {
490 if (P1 == P2 || Depth > MaxDepth)
491 return false;
492 FirstPointers.insert(P1);
493 SecondPointers.insert(P2);
494 P1 = getUnderlyingObject(P1, /*MaxLookup=*/1);
495 P2 = getUnderlyingObject(P2, /*MaxLookup=*/1);
496 ++Depth;
497 }
498 assert((FirstPointers.contains(P2) || SecondPointers.contains(P1)) &&
499 "Unable to find matching root.");
500 return FirstPointers.contains(P2) && !SecondPointers.contains(P1);
501 };
502 for (auto &Base : Bases) {
503 for (auto &Vec : Base.second) {
504 if (Vec.size() > 1) {
506 int64_t InitialOffset = std::get<1>(Vec[0]);
507 bool AnyConsecutive =
508 all_of(enumerate(Vec), [InitialOffset](const auto &P) {
509 return std::get<1>(P.value()) ==
510 int64_t(P.index()) + InitialOffset;
511 });
512 // Fill SortedIndices array only if it looks worth-while to sort the
513 // ptrs.
514 if (!AnyConsecutive)
515 return false;
516 }
517 }
518 stable_sort(Base.second, [&](const auto &V1, const auto &V2) {
519 return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
520 });
521 }
522
523 for (auto &T : Bases)
524 for (const auto &Vec : T.second)
525 for (const auto &P : Vec)
526 SortedIndices.push_back(std::get<2>(P));
527
528 assert(SortedIndices.size() == VL.size() &&
529 "Expected SortedIndices to be the size of VL");
530 return true;
531}
532
533} // namespace llvm::slpvectorizer
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static MaybeAlign getAlign(Value *Ptr)
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
#define I(x, y, z)
Definition MD5.cpp:57
This file implements a map that provides insertion order iteration.
#define T
#define P(N)
This file contains some templates that are useful if you are working with the STL at all.
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
This pass exposes codegen information to IR-level passes.
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
Definition APInt.h:230
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
Get the last element.
Definition ArrayRef.h:150
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
const T & consume_front()
consume_front() - Returns the first element and drops it from ArrayRef.
Definition ArrayRef.h:156
A cache of @llvm.assume calls within a function.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
Class to represent fixed width SIMD vectors.
Information for memory intrinsic cost model.
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 * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEVFlags Flags=SCEV::FlagNone, unsigned Depth=0)
Return LHS-RHS.
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 SCEVUse getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI SCEVUse getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEVFlagsPair Flags={}, unsigned Depth=0)
Get a canonical multiply 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.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void swap(SmallVectorImpl &RHS)
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.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
static LLVM_ABI OperandValueInfo getOperandInfo(const Value *V)
Collect properties of V used in cost analysis, e.g. OP_PowerOf2.
TargetCostKind
The kind of cost model.
@ SK_PermuteSingleSrc
Shuffle elements of single source vector with any shuffle mask.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
Definition Type.h:265
LLVM Value Representation.
Definition Value.h:75
Base class of all SIMD vector types.
An efficient, type-erasing, non-owning reference to a callable.
A private "module" namespace for types and utilities used by this pass.
InstructionCost getShuffleCost(const TargetTransformInfo &TTI, TTI::ShuffleKind Kind, VectorType *Tp, const TTI::TargetCostKind CostKind, ArrayRef< int > Mask, int Index, VectorType *SubTp, ArrayRef< const Value * > Args, TTI::VectorInstrContext VIC)
Returns the cost of the shuffle instructions with the given Kind, vector type Tp and optional Mask.
template Align computeCommonAlignment< StoreInst >(ArrayRef< Value * >)
std::pair< InstructionCost, InstructionCost > getGEPCosts(const TargetTransformInfo &TTI, ArrayRef< Value * > Ptrs, Value *BasePtr, unsigned Opcode, const TTI::TargetCostKind CostKind, Type *ScalarTy, VectorType *VecTy)
Calculate the scalar and the vector costs from vectorizing set of GEPs.
void reorderScalars(SmallVectorImpl< Value * > &Scalars, ArrayRef< int > Mask)
Reorders the list of scalars in accordance with the given Mask.
Definition SLPUtils.cpp:310
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.
Type * getWidenedType(Type *ScalarTy, unsigned VF)
ConstantInt * getStrideBytesIfConstant(Value *Stride, Type *ScalarTy, const DataLayout &DL, bool IsReverse)
Returns Stride scaled by the allocation size of ScalarTy, negated if IsReverse is set,...
static bool buildCompressMask(ArrayRef< Value * > PointerOps, ArrayRef< unsigned > Order, Type *ScalarTy, const DataLayout &DL, ScalarEvolution &SE, SmallVectorImpl< int > &CompressMask)
Builds compress-like mask for shuffles for the given PointerOps, ordered with Order.
void inversePermutation(ArrayRef< unsigned > Indices, SmallVectorImpl< int > &Mask)
Compute the inverse permutation Mask of Indices.
Definition SLPUtils.cpp:301
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)
Checks if the stores VL with pointers PointerOps can be lowered as a single masked store.
InstructionCost getScalarizationOverhead(const TargetTransformInfo &TTI, bool ReVec, Type *ScalarTy, VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, const TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef< Value * > VL, TTI::VectorInstrContext VIC)
This is similar to TargetTransformInfo::getScalarizationOverhead, but if ScalarTy is a FixedVectorTyp...
InstructionsState getSameOpcode(ArrayRef< Value * > VL, const TargetLibraryInfo &TLI)
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 VL can be transformed to a (masked)load + compress or (masked) interleaved load.
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:40
bool clusterSortPtrAccesses(ArrayRef< Value * > VL, ArrayRef< BasicBlock * > BBs, Type *ElemTy, const DataLayout &DL, ScalarEvolution &SE, unsigned MaxDepth, SmallVectorImpl< unsigned > &SortedIndices)
Clusters VL pointers by (basic block, underlying object) pair and sorts each cluster by offset.
unsigned getFullVectorNumberOfElements(const TargetTransformInfo &TTI, Type *Ty, unsigned Sz, bool ReVec)
Returns the number of elements of the given type Ty, not less than Sz, which forms type,...
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Definition STLExtras.h:2132
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
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:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto accumulate(R &&Range, E &&Init)
Wrapper for std::accumulate.
Definition STLExtras.h:1718
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI std::optional< int64_t > getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB, Value *PtrB, const DataLayout &DL, ScalarEvolution &SE, bool StrictCheck=false, bool CheckType=true)
Returns the distance between the pointers PtrA and PtrB iff they are compatible and it is possible to...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
constexpr int PoisonMaskElem
TargetTransformInfo TTI
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:341
LLVM_ABI bool isSafeToLoadUnconditionally(Value *V, Align Alignment, const APInt &Size, const SimplifyQuery &SQ)
Return true if we know that executing a load from this value cannot trap.
Definition Loads.cpp:456
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
A MapVector that performs no allocations if smaller than a certain size.
Definition MapVector.h:342
Function object to check whether the first component of a container supported by std::get (like std::...
Definition STLExtras.h:1455
Function object to check whether the second component of a container supported by std::get (like std:...
Definition STLExtras.h:1464