LLVM 20.0.0git
Delinearization.cpp
Go to the documentation of this file.
1//===---- Delinearization.cpp - MultiDimensional Index Delinearization ----===//
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// This implements an analysis pass that tries to delinearize all GEP
10// instructions in all loops using the SCEV analysis functionality. This pass is
11// only used for testing purposes: if your pass needs delinearization, please
12// use the on-demand SCEVAddRecExpr::delinearize() function.
13//
14//===----------------------------------------------------------------------===//
15
21#include "llvm/IR/Constants.h"
23#include "llvm/IR/Function.h"
26#include "llvm/IR/PassManager.h"
27#include "llvm/Support/Debug.h"
29
30using namespace llvm;
31
32#define DL_NAME "delinearize"
33#define DEBUG_TYPE DL_NAME
34
35// Return true when S contains at least an undef value.
36static inline bool containsUndefs(const SCEV *S) {
37 return SCEVExprContains(S, [](const SCEV *S) {
38 if (const auto *SU = dyn_cast<SCEVUnknown>(S))
39 return isa<UndefValue>(SU->getValue());
40 return false;
41 });
42}
43
44namespace {
45
46// Collect all steps of SCEV expressions.
47struct SCEVCollectStrides {
50
51 SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S)
52 : SE(SE), Strides(S) {}
53
54 bool follow(const SCEV *S) {
55 if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S))
56 Strides.push_back(AR->getStepRecurrence(SE));
57 return true;
58 }
59
60 bool isDone() const { return false; }
61};
62
63// Collect all SCEVUnknown and SCEVMulExpr expressions.
64struct SCEVCollectTerms {
66
67 SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {}
68
69 bool follow(const SCEV *S) {
70 if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) ||
71 isa<SCEVSignExtendExpr>(S)) {
72 if (!containsUndefs(S))
73 Terms.push_back(S);
74
75 // Stop recursion: once we collected a term, do not walk its operands.
76 return false;
77 }
78
79 // Keep looking.
80 return true;
81 }
82
83 bool isDone() const { return false; }
84};
85
86// Check if a SCEV contains an AddRecExpr.
87struct SCEVHasAddRec {
88 bool &ContainsAddRec;
89
90 SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
91 ContainsAddRec = false;
92 }
93
94 bool follow(const SCEV *S) {
95 if (isa<SCEVAddRecExpr>(S)) {
96 ContainsAddRec = true;
97
98 // Stop recursion: once we collected a term, do not walk its operands.
99 return false;
100 }
101
102 // Keep looking.
103 return true;
104 }
105
106 bool isDone() const { return false; }
107};
108
109// Find factors that are multiplied with an expression that (possibly as a
110// subexpression) contains an AddRecExpr. In the expression:
111//
112// 8 * (100 + %p * %q * (%a + {0, +, 1}_loop))
113//
114// "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)"
115// that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size
116// parameters as they form a product with an induction variable.
117//
118// This collector expects all array size parameters to be in the same MulExpr.
119// It might be necessary to later add support for collecting parameters that are
120// spread over different nested MulExpr.
121struct SCEVCollectAddRecMultiplies {
123 ScalarEvolution &SE;
124
125 SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T,
126 ScalarEvolution &SE)
127 : Terms(T), SE(SE) {}
128
129 bool follow(const SCEV *S) {
130 if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
131 bool HasAddRec = false;
133 for (const SCEV *Op : Mul->operands()) {
134 const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
135 if (Unknown && !isa<CallInst>(Unknown->getValue())) {
136 Operands.push_back(Op);
137 } else if (Unknown) {
138 HasAddRec = true;
139 } else {
140 bool ContainsAddRec = false;
141 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
142 visitAll(Op, ContiansAddRec);
143 HasAddRec |= ContainsAddRec;
144 }
145 }
146 if (Operands.size() == 0)
147 return true;
148
149 if (!HasAddRec)
150 return false;
151
152 Terms.push_back(SE.getMulExpr(Operands));
153 // Stop recursion: once we collected a term, do not walk its operands.
154 return false;
155 }
156
157 // Keep looking.
158 return true;
159 }
160
161 bool isDone() const { return false; }
162};
163
164} // end anonymous namespace
165
166/// Find parametric terms in this SCEVAddRecExpr. We first for parameters in
167/// two places:
168/// 1) The strides of AddRec expressions.
169/// 2) Unknowns that are multiplied with AddRec expressions.
173 SCEVCollectStrides StrideCollector(SE, Strides);
174 visitAll(Expr, StrideCollector);
175
176 LLVM_DEBUG({
177 dbgs() << "Strides:\n";
178 for (const SCEV *S : Strides)
179 dbgs() << *S << "\n";
180 });
181
182 for (const SCEV *S : Strides) {
183 SCEVCollectTerms TermCollector(Terms);
184 visitAll(S, TermCollector);
185 }
186
187 LLVM_DEBUG({
188 dbgs() << "Terms:\n";
189 for (const SCEV *T : Terms)
190 dbgs() << *T << "\n";
191 });
192
193 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
194 visitAll(Expr, MulCollector);
195}
196
200 int Last = Terms.size() - 1;
201 const SCEV *Step = Terms[Last];
202
203 // End of recursion.
204 if (Last == 0) {
205 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
207 for (const SCEV *Op : M->operands())
208 if (!isa<SCEVConstant>(Op))
209 Qs.push_back(Op);
210
211 Step = SE.getMulExpr(Qs);
212 }
213
214 Sizes.push_back(Step);
215 return true;
216 }
217
218 for (const SCEV *&Term : Terms) {
219 // Normalize the terms before the next call to findArrayDimensionsRec.
220 const SCEV *Q, *R;
221 SCEVDivision::divide(SE, Term, Step, &Q, &R);
222
223 // Bail out when GCD does not evenly divide one of the terms.
224 if (!R->isZero())
225 return false;
226
227 Term = Q;
228 }
229
230 // Remove all SCEVConstants.
231 erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); });
232
233 if (Terms.size() > 0)
234 if (!findArrayDimensionsRec(SE, Terms, Sizes))
235 return false;
236
237 Sizes.push_back(Step);
238 return true;
239}
240
241// Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter.
243 for (const SCEV *T : Terms)
244 if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); }))
245 return true;
246
247 return false;
248}
249
250// Return the number of product terms in S.
251static inline int numberOfTerms(const SCEV *S) {
252 if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
253 return Expr->getNumOperands();
254 return 1;
255}
256
257static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
258 if (isa<SCEVConstant>(T))
259 return nullptr;
260
261 if (isa<SCEVUnknown>(T))
262 return T;
263
264 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
266 for (const SCEV *Op : M->operands())
267 if (!isa<SCEVConstant>(Op))
268 Factors.push_back(Op);
269
270 return SE.getMulExpr(Factors);
271 }
272
273 return T;
274}
275
279 const SCEV *ElementSize) {
280 if (Terms.size() < 1 || !ElementSize)
281 return;
282
283 // Early return when Terms do not contain parameters: we do not delinearize
284 // non parametric SCEVs.
285 if (!containsParameters(Terms))
286 return;
287
288 LLVM_DEBUG({
289 dbgs() << "Terms:\n";
290 for (const SCEV *T : Terms)
291 dbgs() << *T << "\n";
292 });
293
294 // Remove duplicates.
295 array_pod_sort(Terms.begin(), Terms.end());
296 Terms.erase(llvm::unique(Terms), Terms.end());
297
298 // Put larger terms first.
299 llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) {
301 });
302
303 // Try to divide all terms by the element size. If term is not divisible by
304 // element size, proceed with the original term.
305 for (const SCEV *&Term : Terms) {
306 const SCEV *Q, *R;
307 SCEVDivision::divide(SE, Term, ElementSize, &Q, &R);
308 if (!Q->isZero())
309 Term = Q;
310 }
311
313
314 // Remove constant factors.
315 for (const SCEV *T : Terms)
316 if (const SCEV *NewT = removeConstantFactors(SE, T))
317 NewTerms.push_back(NewT);
318
319 LLVM_DEBUG({
320 dbgs() << "Terms after sorting:\n";
321 for (const SCEV *T : NewTerms)
322 dbgs() << *T << "\n";
323 });
324
325 if (NewTerms.empty() || !findArrayDimensionsRec(SE, NewTerms, Sizes)) {
326 Sizes.clear();
327 return;
328 }
329
330 // The last element to be pushed into Sizes is the size of an element.
331 Sizes.push_back(ElementSize);
332
333 LLVM_DEBUG({
334 dbgs() << "Sizes:\n";
335 for (const SCEV *S : Sizes)
336 dbgs() << *S << "\n";
337 });
338}
339
343 // Early exit in case this SCEV is not an affine multivariate function.
344 if (Sizes.empty())
345 return;
346
347 if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
348 if (!AR->isAffine())
349 return;
350
351 const SCEV *Res = Expr;
352 int Last = Sizes.size() - 1;
353 for (int i = Last; i >= 0; i--) {
354 const SCEV *Q, *R;
355 SCEVDivision::divide(SE, Res, Sizes[i], &Q, &R);
356
357 LLVM_DEBUG({
358 dbgs() << "Res: " << *Res << "\n";
359 dbgs() << "Sizes[i]: " << *Sizes[i] << "\n";
360 dbgs() << "Res divided by Sizes[i]:\n";
361 dbgs() << "Quotient: " << *Q << "\n";
362 dbgs() << "Remainder: " << *R << "\n";
363 });
364
365 Res = Q;
366
367 // Do not record the last subscript corresponding to the size of elements in
368 // the array.
369 if (i == Last) {
370
371 // Bail out if the byte offset is non-zero.
372 if (!R->isZero()) {
373 Subscripts.clear();
374 Sizes.clear();
375 return;
376 }
377
378 continue;
379 }
380
381 // Record the access function for the current subscript.
382 Subscripts.push_back(R);
383 }
384
385 // Also push in last position the remainder of the last division: it will be
386 // the access function of the innermost dimension.
387 Subscripts.push_back(Res);
388
389 std::reverse(Subscripts.begin(), Subscripts.end());
390
391 LLVM_DEBUG({
392 dbgs() << "Subscripts:\n";
393 for (const SCEV *S : Subscripts)
394 dbgs() << *S << "\n";
395 });
396}
397
398/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
399/// sizes of an array access. Returns the remainder of the delinearization that
400/// is the offset start of the array. The SCEV->delinearize algorithm computes
401/// the multiples of SCEV coefficients: that is a pattern matching of sub
402/// expressions in the stride and base of a SCEV corresponding to the
403/// computation of a GCD (greatest common divisor) of base and stride. When
404/// SCEV->delinearize fails, it returns the SCEV unchanged.
405///
406/// For example: when analyzing the memory access A[i][j][k] in this loop nest
407///
408/// void foo(long n, long m, long o, double A[n][m][o]) {
409///
410/// for (long i = 0; i < n; i++)
411/// for (long j = 0; j < m; j++)
412/// for (long k = 0; k < o; k++)
413/// A[i][j][k] = 1.0;
414/// }
415///
416/// the delinearization input is the following AddRec SCEV:
417///
418/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
419///
420/// From this SCEV, we are able to say that the base offset of the access is %A
421/// because it appears as an offset that does not divide any of the strides in
422/// the loops:
423///
424/// CHECK: Base offset: %A
425///
426/// and then SCEV->delinearize determines the size of some of the dimensions of
427/// the array as these are the multiples by which the strides are happening:
428///
429/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double)
430/// bytes.
431///
432/// Note that the outermost dimension remains of UnknownSize because there are
433/// no strides that would help identifying the size of the last dimension: when
434/// the array has been statically allocated, one could compute the size of that
435/// dimension by dividing the overall size of the array by the size of the known
436/// dimensions: %m * %o * 8.
437///
438/// Finally delinearize provides the access functions for the array reference
439/// that does correspond to A[i][j][k] of the above C testcase:
440///
441/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
442///
443/// The testcases are checking the output of a function pass:
444/// DelinearizationPass that walks through all loads and stores of a function
445/// asking for the SCEV of the memory access with respect to all enclosing
446/// loops, calling SCEV->delinearize on that and printing the results.
450 const SCEV *ElementSize) {
451 // First step: collect parametric terms.
453 collectParametricTerms(SE, Expr, Terms);
454
455 if (Terms.empty())
456 return;
457
458 // Second step: find subscript sizes.
459 findArrayDimensions(SE, Terms, Sizes, ElementSize);
460
461 if (Sizes.empty())
462 return;
463
464 // Third step: compute the access functions for each subscript.
465 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
466
467 if (Subscripts.empty())
468 return;
469
470 LLVM_DEBUG({
471 dbgs() << "succeeded to delinearize " << *Expr << "\n";
472 dbgs() << "ArrayDecl[UnknownSize]";
473 for (const SCEV *S : Sizes)
474 dbgs() << "[" << *S << "]";
475
476 dbgs() << "\nArrayRef";
477 for (const SCEV *S : Subscripts)
478 dbgs() << "[" << *S << "]";
479 dbgs() << "\n";
480 });
481}
482
484 const GetElementPtrInst *GEP,
486 SmallVectorImpl<int> &Sizes) {
487 assert(Subscripts.empty() && Sizes.empty() &&
488 "Expected output lists to be empty on entry to this function.");
489 assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
490 Type *Ty = nullptr;
491 bool DroppedFirstDim = false;
492 for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
493 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
494 if (i == 1) {
495 Ty = GEP->getSourceElementType();
496 if (auto *Const = dyn_cast<SCEVConstant>(Expr))
497 if (Const->getValue()->isZero()) {
498 DroppedFirstDim = true;
499 continue;
500 }
501 Subscripts.push_back(Expr);
502 continue;
503 }
504
505 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
506 if (!ArrayTy) {
507 Subscripts.clear();
508 Sizes.clear();
509 return false;
510 }
511
512 Subscripts.push_back(Expr);
513 if (!(DroppedFirstDim && i == 2))
514 Sizes.push_back(ArrayTy->getNumElements());
515
516 Ty = ArrayTy->getElementType();
517 }
518 return !Subscripts.empty();
519}
520
522 ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn,
524 Value *SrcPtr = getLoadStorePointerOperand(Inst);
525
526 // Check the simple case where the array dimensions are fixed size.
527 auto *SrcGEP = dyn_cast<GetElementPtrInst>(SrcPtr);
528 if (!SrcGEP)
529 return false;
530
531 getIndexExpressionsFromGEP(*SE, SrcGEP, Subscripts, Sizes);
532
533 // Check that the two size arrays are non-empty and equal in length and
534 // value.
535 // TODO: it would be better to let the caller to clear Subscripts, similar
536 // to how we handle Sizes.
537 if (Sizes.empty() || Subscripts.size() <= 1) {
538 Subscripts.clear();
539 return false;
540 }
541
542 // Check that for identical base pointers we do not miss index offsets
543 // that have been added before this GEP is applied.
544 Value *SrcBasePtr = SrcGEP->getOperand(0)->stripPointerCasts();
545 const SCEVUnknown *SrcBase =
546 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
547 if (!SrcBase || SrcBasePtr != SrcBase->getValue()) {
548 Subscripts.clear();
549 return false;
550 }
551
552 assert(Subscripts.size() == Sizes.size() + 1 &&
553 "Expected equal number of entries in the list of size and "
554 "subscript.");
555
556 return true;
557}
558
559namespace {
560
561void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
562 ScalarEvolution *SE) {
563 O << "Delinearization on function " << F->getName() << ":\n";
564 for (Instruction &Inst : instructions(F)) {
565 // Only analyze loads and stores.
566 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst) &&
567 !isa<GetElementPtrInst>(&Inst))
568 continue;
569
570 const BasicBlock *BB = Inst.getParent();
571 // Delinearize the memory access as analyzed in all the surrounding loops.
572 // Do not analyze memory accesses outside loops.
573 for (Loop *L = LI->getLoopFor(BB); L != nullptr; L = L->getParentLoop()) {
574 const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
575
576 const SCEVUnknown *BasePointer =
577 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
578 // Do not delinearize if we cannot find the base pointer.
579 if (!BasePointer)
580 break;
581 AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
582
583 O << "\n";
584 O << "Inst:" << Inst << "\n";
585 O << "In Loop with Header: " << L->getHeader()->getName() << "\n";
586 O << "AccessFunction: " << *AccessFn << "\n";
587
588 SmallVector<const SCEV *, 3> Subscripts, Sizes;
589 delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
590 if (Subscripts.size() == 0 || Sizes.size() == 0 ||
591 Subscripts.size() != Sizes.size()) {
592 O << "failed to delinearize\n";
593 continue;
594 }
595
596 O << "Base offset: " << *BasePointer << "\n";
597 O << "ArrayDecl[UnknownSize]";
598 int Size = Subscripts.size();
599 for (int i = 0; i < Size - 1; i++)
600 O << "[" << *Sizes[i] << "]";
601 O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
602
603 O << "ArrayRef";
604 for (int i = 0; i < Size; i++)
605 O << "[" << *Subscripts[i] << "]";
606 O << "\n";
607 }
608 }
609}
610
611} // end anonymous namespace
612
614 : OS(OS) {}
617 printDelinearization(OS, &F, &AM.getResult<LoopAnalysis>(F),
619 return PreservedAnalyses::all();
620}
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define LLVM_DEBUG(...)
Definition: Debug.h:106
static const SCEV * removeConstantFactors(ScalarEvolution &SE, const SCEV *T)
static bool findArrayDimensionsRec(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes)
static bool containsUndefs(const SCEV *S)
static bool containsParameters(SmallVectorImpl< const SCEV * > &Terms)
static int numberOfTerms(const SCEV *S)
uint64_t Size
Hexagon Common GEP
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition: MD5.cpp:55
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
Value * RHS
Value * LHS
BinaryOperator * Mul
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:410
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:219
This class represents an Operation in the Expression.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:933
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:566
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:39
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
This node represents a polynomial recurrence on the trip count of the specified loop.
This node represents multiplication of some number of SCEVs.
This means that we are dealing with an entirely unknown SCEV value, and only represent it as its LLVM...
This class represents an analyzed expression in the program.
bool isZero() const
Return true if the expression is a constant zero.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
const SCEV * getMulExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
bool empty() const
Definition: SmallVector.h:81
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
iterator erase(const_iterator CI)
Definition: SmallVector.h:737
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
op_range operands()
Definition: User.h:288
LLVM Value Representation.
Definition: Value.h:74
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:694
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void visitAll(const SCEV *Root, SV &Visitor)
Use SCEVTraversal to visit all nodes in the given expression tree.
void collectParametricTerms(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Terms)
Collect parametric terms occurring in step expressions (first step of delinearization).
void findArrayDimensions(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Compute the array dimensions Sizes from the set of Terms extracted from the memory access function of...
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
auto unique(Range &&R, Predicate P)
Definition: STLExtras.h:2055
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
void computeAccessFunctions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Return in Subscripts the access functions for each dimension in Sizes (third step of delinearization)...
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
bool getIndexExpressionsFromGEP(ScalarEvolution &SE, const GetElementPtrInst *GEP, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Gathers the individual index expressions from a GEP instruction.
bool tryDelinearizeFixedSizeImpl(ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< int > &Sizes)
Implementation of fixed size array delinearization.
void delinearize(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes, const SCEV *ElementSize)
Split this SCEVAddRecExpr into two vectors of SCEVs representing the subscripts and sizes of an array...
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
Definition: STLExtras.h:2099
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
Definition: STLExtras.h:1624
bool SCEVExprContains(const SCEV *Root, PredTy Pred)
Return true if any node in Root satisfies the predicate Pred.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static void divide(ScalarEvolution &SE, const SCEV *Numerator, const SCEV *Denominator, const SCEV **Quotient, const SCEV **Remainder)