LLVM 22.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"
28#include "llvm/Support/Debug.h"
30
31using namespace llvm;
32
33#define DL_NAME "delinearize"
34#define DEBUG_TYPE DL_NAME
35
37 "delinearize-use-fixed-size-array-heuristic", cl::init(false), cl::Hidden,
38 cl::desc("When printing analysis, use the heuristic for fixed-size arrays "
39 "if the default delinearizetion fails."));
40
41// Return true when S contains at least an undef value.
42static inline bool containsUndefs(const SCEV *S) {
43 return SCEVExprContains(S, [](const SCEV *S) {
44 if (const auto *SU = dyn_cast<SCEVUnknown>(S))
45 return isa<UndefValue>(SU->getValue());
46 return false;
47 });
48}
49
50namespace {
51
52// Collect all steps of SCEV expressions.
53struct SCEVCollectStrides {
56
57 SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S)
58 : SE(SE), Strides(S) {}
59
60 bool follow(const SCEV *S) {
61 if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S))
62 Strides.push_back(AR->getStepRecurrence(SE));
63 return true;
64 }
65
66 bool isDone() const { return false; }
67};
68
69// Collect all SCEVUnknown and SCEVMulExpr expressions.
70struct SCEVCollectTerms {
72
73 SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {}
74
75 bool follow(const SCEV *S) {
76 if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S) ||
77 isa<SCEVSignExtendExpr>(S)) {
78 if (!containsUndefs(S))
79 Terms.push_back(S);
80
81 // Stop recursion: once we collected a term, do not walk its operands.
82 return false;
83 }
84
85 // Keep looking.
86 return true;
87 }
88
89 bool isDone() const { return false; }
90};
91
92// Check if a SCEV contains an AddRecExpr.
93struct SCEVHasAddRec {
94 bool &ContainsAddRec;
95
96 SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
97 ContainsAddRec = false;
98 }
99
100 bool follow(const SCEV *S) {
101 if (isa<SCEVAddRecExpr>(S)) {
102 ContainsAddRec = true;
103
104 // Stop recursion: once we collected a term, do not walk its operands.
105 return false;
106 }
107
108 // Keep looking.
109 return true;
110 }
111
112 bool isDone() const { return false; }
113};
114
115// Find factors that are multiplied with an expression that (possibly as a
116// subexpression) contains an AddRecExpr. In the expression:
117//
118// 8 * (100 + %p * %q * (%a + {0, +, 1}_loop))
119//
120// "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)"
121// that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size
122// parameters as they form a product with an induction variable.
123//
124// This collector expects all array size parameters to be in the same MulExpr.
125// It might be necessary to later add support for collecting parameters that are
126// spread over different nested MulExpr.
127struct SCEVCollectAddRecMultiplies {
129 ScalarEvolution &SE;
130
131 SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T,
132 ScalarEvolution &SE)
133 : Terms(T), SE(SE) {}
134
135 bool follow(const SCEV *S) {
136 if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
137 bool HasAddRec = false;
139 for (const SCEV *Op : Mul->operands()) {
140 const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
141 if (Unknown && !isa<CallInst>(Unknown->getValue())) {
142 Operands.push_back(Op);
143 } else if (Unknown) {
144 HasAddRec = true;
145 } else {
146 bool ContainsAddRec = false;
147 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
148 visitAll(Op, ContiansAddRec);
149 HasAddRec |= ContainsAddRec;
150 }
151 }
152 if (Operands.size() == 0)
153 return true;
154
155 if (!HasAddRec)
156 return false;
157
158 Terms.push_back(SE.getMulExpr(Operands));
159 // Stop recursion: once we collected a term, do not walk its operands.
160 return false;
161 }
162
163 // Keep looking.
164 return true;
165 }
166
167 bool isDone() const { return false; }
168};
169
170} // end anonymous namespace
171
172/// Find parametric terms in this SCEVAddRecExpr. We first for parameters in
173/// two places:
174/// 1) The strides of AddRec expressions.
175/// 2) Unknowns that are multiplied with AddRec expressions.
179 SCEVCollectStrides StrideCollector(SE, Strides);
180 visitAll(Expr, StrideCollector);
181
182 LLVM_DEBUG({
183 dbgs() << "Strides:\n";
184 for (const SCEV *S : Strides)
185 dbgs() << *S << "\n";
186 });
187
188 for (const SCEV *S : Strides) {
189 SCEVCollectTerms TermCollector(Terms);
190 visitAll(S, TermCollector);
191 }
192
193 LLVM_DEBUG({
194 dbgs() << "Terms:\n";
195 for (const SCEV *T : Terms)
196 dbgs() << *T << "\n";
197 });
198
199 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
200 visitAll(Expr, MulCollector);
201}
202
206 int Last = Terms.size() - 1;
207 const SCEV *Step = Terms[Last];
208
209 // End of recursion.
210 if (Last == 0) {
211 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
213 for (const SCEV *Op : M->operands())
214 if (!isa<SCEVConstant>(Op))
215 Qs.push_back(Op);
216
217 Step = SE.getMulExpr(Qs);
218 }
219
220 Sizes.push_back(Step);
221 return true;
222 }
223
224 for (const SCEV *&Term : Terms) {
225 // Normalize the terms before the next call to findArrayDimensionsRec.
226 const SCEV *Q, *R;
227 SCEVDivision::divide(SE, Term, Step, &Q, &R);
228
229 // Bail out when GCD does not evenly divide one of the terms.
230 if (!R->isZero())
231 return false;
232
233 Term = Q;
234 }
235
236 // Remove all SCEVConstants.
237 erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); });
238
239 if (Terms.size() > 0)
240 if (!findArrayDimensionsRec(SE, Terms, Sizes))
241 return false;
242
243 Sizes.push_back(Step);
244 return true;
245}
246
247// Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter.
249 for (const SCEV *T : Terms)
250 if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); }))
251 return true;
252
253 return false;
254}
255
256// Return the number of product terms in S.
257static inline int numberOfTerms(const SCEV *S) {
258 if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
259 return Expr->getNumOperands();
260 return 1;
261}
262
263static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
264 if (isa<SCEVConstant>(T))
265 return nullptr;
266
267 if (isa<SCEVUnknown>(T))
268 return T;
269
270 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
272 for (const SCEV *Op : M->operands())
273 if (!isa<SCEVConstant>(Op))
274 Factors.push_back(Op);
275
276 return SE.getMulExpr(Factors);
277 }
278
279 return T;
280}
281
285 const SCEV *ElementSize) {
286 if (Terms.size() < 1 || !ElementSize)
287 return;
288
289 // Early return when Terms do not contain parameters: we do not delinearize
290 // non parametric SCEVs.
291 if (!containsParameters(Terms))
292 return;
293
294 LLVM_DEBUG({
295 dbgs() << "Terms:\n";
296 for (const SCEV *T : Terms)
297 dbgs() << *T << "\n";
298 });
299
300 // Remove duplicates.
301 array_pod_sort(Terms.begin(), Terms.end());
302 Terms.erase(llvm::unique(Terms), Terms.end());
303
304 // Put larger terms first.
305 llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) {
307 });
308
309 // Try to divide all terms by the element size. If term is not divisible by
310 // element size, proceed with the original term.
311 for (const SCEV *&Term : Terms) {
312 const SCEV *Q, *R;
313 SCEVDivision::divide(SE, Term, ElementSize, &Q, &R);
314 if (!Q->isZero())
315 Term = Q;
316 }
317
319
320 // Remove constant factors.
321 for (const SCEV *T : Terms)
322 if (const SCEV *NewT = removeConstantFactors(SE, T))
323 NewTerms.push_back(NewT);
324
325 LLVM_DEBUG({
326 dbgs() << "Terms after sorting:\n";
327 for (const SCEV *T : NewTerms)
328 dbgs() << *T << "\n";
329 });
330
331 if (NewTerms.empty() || !findArrayDimensionsRec(SE, NewTerms, Sizes)) {
332 Sizes.clear();
333 return;
334 }
335
336 // The last element to be pushed into Sizes is the size of an element.
337 Sizes.push_back(ElementSize);
338
339 LLVM_DEBUG({
340 dbgs() << "Sizes:\n";
341 for (const SCEV *S : Sizes)
342 dbgs() << *S << "\n";
343 });
344}
345
349 // Early exit in case this SCEV is not an affine multivariate function.
350 if (Sizes.empty())
351 return;
352
353 if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
354 if (!AR->isAffine())
355 return;
356
357 const SCEV *Res = Expr;
358 int Last = Sizes.size() - 1;
359 for (int i = Last; i >= 0; i--) {
360 const SCEV *Q, *R;
361 SCEVDivision::divide(SE, Res, Sizes[i], &Q, &R);
362
363 LLVM_DEBUG({
364 dbgs() << "Res: " << *Res << "\n";
365 dbgs() << "Sizes[i]: " << *Sizes[i] << "\n";
366 dbgs() << "Res divided by Sizes[i]:\n";
367 dbgs() << "Quotient: " << *Q << "\n";
368 dbgs() << "Remainder: " << *R << "\n";
369 });
370
371 Res = Q;
372
373 // Do not record the last subscript corresponding to the size of elements in
374 // the array.
375 if (i == Last) {
376
377 // Bail out if the byte offset is non-zero.
378 if (!R->isZero()) {
379 Subscripts.clear();
380 Sizes.clear();
381 return;
382 }
383
384 continue;
385 }
386
387 // Record the access function for the current subscript.
388 Subscripts.push_back(R);
389 }
390
391 // Also push in last position the remainder of the last division: it will be
392 // the access function of the innermost dimension.
393 Subscripts.push_back(Res);
394
395 std::reverse(Subscripts.begin(), Subscripts.end());
396
397 LLVM_DEBUG({
398 dbgs() << "Subscripts:\n";
399 for (const SCEV *S : Subscripts)
400 dbgs() << *S << "\n";
401 });
402}
403
404/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
405/// sizes of an array access. Returns the remainder of the delinearization that
406/// is the offset start of the array. The SCEV->delinearize algorithm computes
407/// the multiples of SCEV coefficients: that is a pattern matching of sub
408/// expressions in the stride and base of a SCEV corresponding to the
409/// computation of a GCD (greatest common divisor) of base and stride. When
410/// SCEV->delinearize fails, it returns the SCEV unchanged.
411///
412/// For example: when analyzing the memory access A[i][j][k] in this loop nest
413///
414/// void foo(long n, long m, long o, double A[n][m][o]) {
415///
416/// for (long i = 0; i < n; i++)
417/// for (long j = 0; j < m; j++)
418/// for (long k = 0; k < o; k++)
419/// A[i][j][k] = 1.0;
420/// }
421///
422/// the delinearization input is the following AddRec SCEV:
423///
424/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
425///
426/// From this SCEV, we are able to say that the base offset of the access is %A
427/// because it appears as an offset that does not divide any of the strides in
428/// the loops:
429///
430/// CHECK: Base offset: %A
431///
432/// and then SCEV->delinearize determines the size of some of the dimensions of
433/// the array as these are the multiples by which the strides are happening:
434///
435/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double)
436/// bytes.
437///
438/// Note that the outermost dimension remains of UnknownSize because there are
439/// no strides that would help identifying the size of the last dimension: when
440/// the array has been statically allocated, one could compute the size of that
441/// dimension by dividing the overall size of the array by the size of the known
442/// dimensions: %m * %o * 8.
443///
444/// Finally delinearize provides the access functions for the array reference
445/// that does correspond to A[i][j][k] of the above C testcase:
446///
447/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
448///
449/// The testcases are checking the output of a function pass:
450/// DelinearizationPass that walks through all loads and stores of a function
451/// asking for the SCEV of the memory access with respect to all enclosing
452/// loops, calling SCEV->delinearize on that and printing the results.
456 const SCEV *ElementSize) {
457 // First step: collect parametric terms.
459 collectParametricTerms(SE, Expr, Terms);
460
461 if (Terms.empty())
462 return;
463
464 // Second step: find subscript sizes.
465 findArrayDimensions(SE, Terms, Sizes, ElementSize);
466
467 if (Sizes.empty())
468 return;
469
470 // Third step: compute the access functions for each subscript.
471 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
472
473 if (Subscripts.empty())
474 return;
475
476 LLVM_DEBUG({
477 dbgs() << "succeeded to delinearize " << *Expr << "\n";
478 dbgs() << "ArrayDecl[UnknownSize]";
479 for (const SCEV *S : Sizes)
480 dbgs() << "[" << *S << "]";
481
482 dbgs() << "\nArrayRef";
483 for (const SCEV *S : Subscripts)
484 dbgs() << "[" << *S << "]";
485 dbgs() << "\n";
486 });
487}
488
489static std::optional<APInt> tryIntoAPInt(const SCEV *S) {
490 if (const auto *Const = dyn_cast<SCEVConstant>(S))
491 return Const->getAPInt();
492 return std::nullopt;
493}
494
495/// Collects the absolute values of constant steps for all induction variables.
496/// Returns true if we can prove that all step recurrences are constants and \p
497/// Expr is divisible by \p ElementSize. Each step recurrence is stored in \p
498/// Steps after divided by \p ElementSize.
499static bool collectConstantAbsSteps(ScalarEvolution &SE, const SCEV *Expr,
501 uint64_t ElementSize) {
502 // End of recursion. The constant value also must be a multiple of
503 // ElementSize.
504 if (const auto *Const = dyn_cast<SCEVConstant>(Expr)) {
505 const uint64_t Mod = Const->getAPInt().urem(ElementSize);
506 return Mod == 0;
507 }
508
509 const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Expr);
510 if (!AR || !AR->isAffine())
511 return false;
512
513 const SCEV *Step = AR->getStepRecurrence(SE);
514 std::optional<APInt> StepAPInt = tryIntoAPInt(Step);
515 if (!StepAPInt)
516 return false;
517
518 APInt Q;
519 uint64_t R;
520 APInt::udivrem(StepAPInt->abs(), ElementSize, Q, R);
521 if (R != 0)
522 return false;
523
524 // Bail out when the step is too large.
525 std::optional<uint64_t> StepVal = Q.tryZExtValue();
526 if (!StepVal)
527 return false;
528
529 Steps.push_back(*StepVal);
530 return collectConstantAbsSteps(SE, AR->getStart(), Steps, ElementSize);
531}
532
535 const SCEV *ElementSize) {
536 if (!ElementSize)
537 return false;
538
539 std::optional<APInt> ElementSizeAPInt = tryIntoAPInt(ElementSize);
540 if (!ElementSizeAPInt || *ElementSizeAPInt == 0)
541 return false;
542
543 std::optional<uint64_t> ElementSizeConst = ElementSizeAPInt->tryZExtValue();
544
545 // Early exit when ElementSize is not a positive constant.
546 if (!ElementSizeConst)
547 return false;
548
549 if (!collectConstantAbsSteps(SE, Expr, Sizes, *ElementSizeConst) ||
550 Sizes.empty()) {
551 Sizes.clear();
552 return false;
553 }
554
555 // At this point, Sizes contains the absolute step recurrences for all
556 // induction variables. Each step recurrence must be a multiple of the size of
557 // the array element. Assuming that the each value represents the size of an
558 // array for each dimension, attempts to restore the length of each dimension
559 // by dividing the step recurrence by the next smaller value. For example, if
560 // we have the following AddRec SCEV:
561 //
562 // AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
563 //
564 // Then Sizes will become [256, 32, 1] after sorted. We don't know the size of
565 // the outermost dimension, the next dimension will be computed as 256 / 32 =
566 // 8, and the last dimension will be computed as 32 / 1 = 32. Thus it results
567 // in like Arr[UnknownSize][8][32] with elements of size 8 bytes, where Arr is
568 // a base pointer.
569 //
570 // TODO: Catch more cases, e.g., when a step recurrence is not divisible by
571 // the next smaller one, like A[i][3*j].
572 llvm::sort(Sizes.rbegin(), Sizes.rend());
573 Sizes.erase(llvm::unique(Sizes), Sizes.end());
574
575 // The last element in Sizes should be ElementSize. At this point, all values
576 // in Sizes are assumed to be divided by ElementSize, so replace it with 1.
577 assert(Sizes.back() != 0 && "Unexpected zero size in Sizes.");
578 Sizes.back() = 1;
579
580 for (unsigned I = 0; I + 1 < Sizes.size(); I++) {
581 uint64_t PrevSize = Sizes[I + 1];
582 if (Sizes[I] % PrevSize) {
583 Sizes.clear();
584 return false;
585 }
586 Sizes[I] /= PrevSize;
587 }
588
589 // Finally, the last element in Sizes should be ElementSize.
590 Sizes.back() = *ElementSizeConst;
591 return true;
592}
593
594/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
595/// sizes of an array access, assuming that the array is a fixed size array.
596///
597/// E.g., if we have the code like as follows:
598///
599/// double A[42][8][32];
600/// for i
601/// for j
602/// for k
603/// use A[i][j][k]
604///
605/// The access function will be represented as an AddRec SCEV like:
606///
607/// AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
608///
609/// Then findFixedSizeArrayDimensions infers the size of each dimension of the
610/// array based on the fact that the value of the step recurrence is a multiple
611/// of the size of the corresponding array element. In the above example, it
612/// results in the following:
613///
614/// CHECK: ArrayDecl[UnknownSize][8][32] with elements of 8 bytes.
615///
616/// Finally each subscript will be computed as follows:
617///
618/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
619///
620/// Note that this function doesn't check the range of possible values for each
621/// subscript, so the caller should perform additional boundary checks if
622/// necessary.
623///
624/// Also note that this function doesn't guarantee that the original array size
625/// is restored "correctly". For example, in the following case:
626///
627/// double A[42][4][64];
628/// double B[42][8][32];
629/// for i
630/// for j
631/// for k
632/// use A[i][j][k]
633/// use B[i][2*j][k]
634///
635/// The access function for both accesses will be the same:
636///
637/// AddRec: {{{0,+,2048}<%for.i>,+,512}<%for.j>,+,8}<%for.k> (ElementSize=8)
638///
639/// The array sizes for both A and B will be computed as
640/// ArrayDecl[UnknownSize][4][64], which matches for A, but not for B.
641///
642/// TODO: At the moment, this function can handle only simple cases. For
643/// example, we cannot handle a case where a step recurrence is not divisible
644/// by the next smaller step recurrence, e.g., A[i][3*j].
648 const SCEV *ElementSize) {
649
650 // First step: find the fixed array size.
651 SmallVector<uint64_t, 4> ConstSizes;
652 if (!findFixedSizeArrayDimensions(SE, Expr, ConstSizes, ElementSize)) {
653 Sizes.clear();
654 return false;
655 }
656
657 // Convert the constant size to SCEV.
658 for (uint64_t Size : ConstSizes)
659 Sizes.push_back(SE.getConstant(Expr->getType(), Size));
660
661 // Second step: compute the access functions for each subscript.
662 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
663
664 return !Subscripts.empty();
665}
666
668 const GetElementPtrInst *GEP,
670 SmallVectorImpl<int> &Sizes) {
671 assert(Subscripts.empty() && Sizes.empty() &&
672 "Expected output lists to be empty on entry to this function.");
673 assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
674 Type *Ty = nullptr;
675 bool DroppedFirstDim = false;
676 for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
677 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
678 if (i == 1) {
679 Ty = GEP->getSourceElementType();
680 if (auto *Const = dyn_cast<SCEVConstant>(Expr))
681 if (Const->getValue()->isZero()) {
682 DroppedFirstDim = true;
683 continue;
684 }
685 Subscripts.push_back(Expr);
686 continue;
687 }
688
689 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
690 if (!ArrayTy) {
691 Subscripts.clear();
692 Sizes.clear();
693 return false;
694 }
695
696 Subscripts.push_back(Expr);
697 if (!(DroppedFirstDim && i == 2))
698 Sizes.push_back(ArrayTy->getNumElements());
699
700 Ty = ArrayTy->getElementType();
701 }
702 return !Subscripts.empty();
703}
704
706 ScalarEvolution *SE, Instruction *Inst, const SCEV *AccessFn,
708 Value *SrcPtr = getLoadStorePointerOperand(Inst);
709
710 // Check the simple case where the array dimensions are fixed size.
711 auto *SrcGEP = dyn_cast<GetElementPtrInst>(SrcPtr);
712 if (!SrcGEP)
713 return false;
714
715 getIndexExpressionsFromGEP(*SE, SrcGEP, Subscripts, Sizes);
716
717 // Check that the two size arrays are non-empty and equal in length and
718 // value.
719 // TODO: it would be better to let the caller to clear Subscripts, similar
720 // to how we handle Sizes.
721 if (Sizes.empty() || Subscripts.size() <= 1) {
722 Subscripts.clear();
723 return false;
724 }
725
726 // Check that for identical base pointers we do not miss index offsets
727 // that have been added before this GEP is applied.
728 Value *SrcBasePtr = SrcGEP->getOperand(0)->stripPointerCasts();
729 const SCEVUnknown *SrcBase =
730 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
731 if (!SrcBase || SrcBasePtr != SrcBase->getValue()) {
732 Subscripts.clear();
733 return false;
734 }
735
736 assert(Subscripts.size() == Sizes.size() + 1 &&
737 "Expected equal number of entries in the list of size and "
738 "subscript.");
739
740 return true;
741}
742
743namespace {
744
745void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
746 ScalarEvolution *SE) {
747 O << "Printing analysis 'Delinearization' for function '" << F->getName()
748 << "':";
749 for (Instruction &Inst : instructions(F)) {
750 // Only analyze loads and stores.
751 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst))
752 continue;
753
754 const BasicBlock *BB = Inst.getParent();
755 Loop *L = LI->getLoopFor(BB);
756 // Only delinearize the memory access in the innermost loop.
757 // Do not analyze memory accesses outside loops.
758 if (!L)
759 continue;
760
761 const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
762
763 const SCEVUnknown *BasePointer =
764 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFn));
765 // Do not delinearize if we cannot find the base pointer.
766 if (!BasePointer)
767 break;
768 AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
769
770 O << "\n";
771 O << "Inst:" << Inst << "\n";
772 O << "In Loop with Header: " << L->getHeader()->getName() << "\n";
773 O << "AccessFunction: " << *AccessFn << "\n";
774
775 SmallVector<const SCEV *, 3> Subscripts, Sizes;
776
777 auto IsDelinearizationFailed = [&]() {
778 return Subscripts.size() == 0 || Sizes.size() == 0 ||
779 Subscripts.size() != Sizes.size();
780 };
781
782 delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
783 if (UseFixedSizeArrayHeuristic && IsDelinearizationFailed()) {
784 Subscripts.clear();
785 Sizes.clear();
786 delinearizeFixedSizeArray(*SE, AccessFn, Subscripts, Sizes,
787 SE->getElementSize(&Inst));
788 }
789
790 if (IsDelinearizationFailed()) {
791 O << "failed to delinearize\n";
792 continue;
793 }
794
795 O << "Base offset: " << *BasePointer << "\n";
796 O << "ArrayDecl[UnknownSize]";
797 int Size = Subscripts.size();
798 for (int i = 0; i < Size - 1; i++)
799 O << "[" << *Sizes[i] << "]";
800 O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
801
802 O << "ArrayRef";
803 for (int i = 0; i < Size; i++)
804 O << "[" << *Subscripts[i] << "]";
805 O << "\n";
806 }
807}
808
809} // end anonymous namespace
810
812 : OS(OS) {}
815 printDelinearization(OS, &F, &AM.getResult<LoopAnalysis>(F),
817 return PreservedAnalyses::all();
818}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static const SCEV * removeConstantFactors(ScalarEvolution &SE, const SCEV *T)
static bool collectConstantAbsSteps(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< uint64_t > &Steps, uint64_t ElementSize)
Collects the absolute values of constant steps for all induction variables.
static cl::opt< bool > UseFixedSizeArrayHeuristic("delinearize-use-fixed-size-array-heuristic", cl::init(false), cl::Hidden, cl::desc("When printing analysis, use the heuristic for fixed-size arrays " "if the default delinearizetion fails."))
static bool findArrayDimensionsRec(ScalarEvolution &SE, SmallVectorImpl< const SCEV * > &Terms, SmallVectorImpl< const SCEV * > &Sizes)
static bool containsUndefs(const SCEV *S)
static std::optional< APInt > tryIntoAPInt(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
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
raw_pwrite_stream & OS
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Value * RHS
Value * LHS
BinaryOperator * Mul
Class for arbitrary precision integers.
Definition: APInt.h:78
std::optional< uint64_t > tryZExtValue() const
Get zero extended value if possible.
Definition: APInt.h:1552
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
Definition: APInt.cpp:1758
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:213
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:949
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:570
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:40
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
This node represents a polynomial recurrence on the trip count of the specified loop.
const SCEV * getStepRecurrence(ScalarEvolution &SE) const
Constructs and returns the recurrence indicating how much this expression steps by.
bool isAffine() const
Return true if this represents an expression A + B*x where A and B are loop invariant values.
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.
LLVM_ABI bool isZero() const
Return true if the expression is a constant zero.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
Analysis pass that exposes the ScalarEvolution for a function.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
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(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getPointerBase(const SCEV *V)
Transitively follow the chain of pointer-type operands until reaching a SCEV that does not have a sin...
LLVM_ABI 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.
LLVM_ABI const SCEV * getElementSize(Instruction *Inst)
Return the size of an element read or written by Inst.
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
iterator erase(const_iterator CI)
Definition: SmallVector.h:738
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
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:292
LLVM Value Representation.
Definition: Value.h:75
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:701
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
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:2095
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)...
bool delinearizeFixedSizeArray(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 acces...
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
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...
bool findFixedSizeArrayDimensions(ScalarEvolution &SE, const SCEV *Expr, SmallVectorImpl< uint64_t > &Sizes, const SCEV *ElementSize)
Compute the dimensions of fixed size array from \Expr and save the results in Sizes.
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:2139
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:1629
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)
Computes the Quotient and Remainder of the division of Numerator by Denominator.