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 {
54 ScalarEvolution &SE;
55 SmallVectorImpl<const SCEV *> &Strides;
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 {
71 SmallVectorImpl<const SCEV *> &Terms;
72
73 SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {}
74
75 bool follow(const SCEV *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 {
128 SmallVectorImpl<const SCEV *> &Terms;
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().indent(2) << *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().indent(2) << *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().indent(2) << *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) {
306 return numberOfTerms(LHS) > numberOfTerms(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().indent(2) << *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().indent(2) << *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 // Clear output vector.
358 Subscripts.clear();
359
360 LLVM_DEBUG(dbgs() << "\ncomputeAccessFunctions\n"
361 << "Memory Access Function: " << *Expr << "\n");
362
363 const SCEV *Res = Expr;
364 int Last = Sizes.size() - 1;
365
366 for (int i = Last; i >= 0; i--) {
367 const SCEV *Size = Sizes[i];
368 const SCEV *Q, *R;
369
370 SCEVDivision::divide(SE, Res, Size, &Q, &R);
371
372 LLVM_DEBUG({
373 dbgs() << "Computing 'MemAccFn / Sizes[" << i << "]':\n";
374 dbgs() << " MemAccFn: " << *Res << "\n";
375 dbgs() << " Sizes[" << i << "]: " << *Size << "\n";
376 dbgs() << " Quotient (Leftover): " << *Q << "\n";
377 dbgs() << " Remainder (Subscript Access Function): " << *R << "\n";
378 });
379
380 Res = Q;
381
382 // Do not record the last subscript corresponding to the size of elements in
383 // the array.
384 if (i == Last) {
385
386 // Bail out if the byte offset is non-zero.
387 if (!R->isZero()) {
388 Subscripts.clear();
389 Sizes.clear();
390 return;
391 }
392
393 continue;
394 }
395
396 // Record the access function for the current subscript.
397 Subscripts.push_back(R);
398 }
399
400 // Also push in last position the remainder of the last division: it will be
401 // the access function of the innermost dimension.
402 Subscripts.push_back(Res);
403
404 std::reverse(Subscripts.begin(), Subscripts.end());
405
406 LLVM_DEBUG({
407 dbgs() << "Subscripts:\n";
408 for (const SCEV *S : Subscripts)
409 dbgs().indent(2) << *S << "\n";
410 dbgs() << "\n";
411 });
412}
413
414/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
415/// sizes of an array access. Returns the remainder of the delinearization that
416/// is the offset start of the array. The SCEV->delinearize algorithm computes
417/// the multiples of SCEV coefficients: that is a pattern matching of sub
418/// expressions in the stride and base of a SCEV corresponding to the
419/// computation of a GCD (greatest common divisor) of base and stride. When
420/// SCEV->delinearize fails, it returns the SCEV unchanged.
421///
422/// For example: when analyzing the memory access A[i][j][k] in this loop nest
423///
424/// void foo(long n, long m, long o, double A[n][m][o]) {
425///
426/// for (long i = 0; i < n; i++)
427/// for (long j = 0; j < m; j++)
428/// for (long k = 0; k < o; k++)
429/// A[i][j][k] = 1.0;
430/// }
431///
432/// the delinearization input is the following AddRec SCEV:
433///
434/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
435///
436/// From this SCEV, we are able to say that the base offset of the access is %A
437/// because it appears as an offset that does not divide any of the strides in
438/// the loops:
439///
440/// CHECK: Base offset: %A
441///
442/// and then SCEV->delinearize determines the size of some of the dimensions of
443/// the array as these are the multiples by which the strides are happening:
444///
445/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double)
446/// bytes.
447///
448/// Note that the outermost dimension remains of UnknownSize because there are
449/// no strides that would help identifying the size of the last dimension: when
450/// the array has been statically allocated, one could compute the size of that
451/// dimension by dividing the overall size of the array by the size of the known
452/// dimensions: %m * %o * 8.
453///
454/// Finally delinearize provides the access functions for the array reference
455/// that does correspond to A[i][j][k] of the above C testcase:
456///
457/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
458///
459/// The testcases are checking the output of a function pass:
460/// DelinearizationPass that walks through all loads and stores of a function
461/// asking for the SCEV of the memory access with respect to all enclosing
462/// loops, calling SCEV->delinearize on that and printing the results.
466 const SCEV *ElementSize) {
467 // Clear output vectors.
468 Subscripts.clear();
469 Sizes.clear();
470
471 // First step: collect parametric terms.
473 collectParametricTerms(SE, Expr, Terms);
474
475 if (Terms.empty())
476 return;
477
478 // Second step: find subscript sizes.
479 findArrayDimensions(SE, Terms, Sizes, ElementSize);
480
481 if (Sizes.empty())
482 return;
483
484 // Third step: compute the access functions for each subscript.
485 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
486}
487
488static std::optional<APInt> tryIntoAPInt(const SCEV *S) {
489 if (const auto *Const = dyn_cast<SCEVConstant>(S))
490 return Const->getAPInt();
491 return std::nullopt;
492}
493
494/// Collects the absolute values of constant steps for all induction variables.
495/// Returns true if we can prove that all step recurrences are constants and \p
496/// Expr is divisible by \p ElementSize. Each step recurrence is stored in \p
497/// Steps after divided by \p ElementSize.
498static bool collectConstantAbsSteps(ScalarEvolution &SE, const SCEV *Expr,
500 uint64_t ElementSize) {
501 // End of recursion. The constant value also must be a multiple of
502 // ElementSize.
503 if (const auto *Const = dyn_cast<SCEVConstant>(Expr)) {
504 const uint64_t Mod = Const->getAPInt().urem(ElementSize);
505 return Mod == 0;
506 }
507
509 if (!AR || !AR->isAffine())
510 return false;
511
512 const SCEV *Step = AR->getStepRecurrence(SE);
513 std::optional<APInt> StepAPInt = tryIntoAPInt(Step);
514 if (!StepAPInt)
515 return false;
516
517 APInt Q;
518 uint64_t R;
519 APInt::udivrem(StepAPInt->abs(), ElementSize, Q, R);
520 if (R != 0)
521 return false;
522
523 // Bail out when the step is too large.
524 std::optional<uint64_t> StepVal = Q.tryZExtValue();
525 if (!StepVal)
526 return false;
527
528 Steps.push_back(*StepVal);
529 return collectConstantAbsSteps(SE, AR->getStart(), Steps, ElementSize);
530}
531
534 const SCEV *ElementSize) {
535 if (!ElementSize)
536 return false;
537
538 std::optional<APInt> ElementSizeAPInt = tryIntoAPInt(ElementSize);
539 if (!ElementSizeAPInt || *ElementSizeAPInt == 0)
540 return false;
541
542 std::optional<uint64_t> ElementSizeConst = ElementSizeAPInt->tryZExtValue();
543
544 // Early exit when ElementSize is not a positive constant.
545 if (!ElementSizeConst)
546 return false;
547
548 if (!collectConstantAbsSteps(SE, Expr, Sizes, *ElementSizeConst) ||
549 Sizes.empty()) {
550 Sizes.clear();
551 return false;
552 }
553
554 // At this point, Sizes contains the absolute step recurrences for all
555 // induction variables. Each step recurrence must be a multiple of the size of
556 // the array element. Assuming that the each value represents the size of an
557 // array for each dimension, attempts to restore the length of each dimension
558 // by dividing the step recurrence by the next smaller value. For example, if
559 // we have the following AddRec SCEV:
560 //
561 // AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
562 //
563 // Then Sizes will become [256, 32, 1] after sorted. We don't know the size of
564 // the outermost dimension, the next dimension will be computed as 256 / 32 =
565 // 8, and the last dimension will be computed as 32 / 1 = 32. Thus it results
566 // in like Arr[UnknownSize][8][32] with elements of size 8 bytes, where Arr is
567 // a base pointer.
568 //
569 // TODO: Catch more cases, e.g., when a step recurrence is not divisible by
570 // the next smaller one, like A[i][3*j].
571 llvm::sort(Sizes.rbegin(), Sizes.rend());
572 Sizes.erase(llvm::unique(Sizes), Sizes.end());
573
574 // The last element in Sizes should be ElementSize. At this point, all values
575 // in Sizes are assumed to be divided by ElementSize, so replace it with 1.
576 assert(Sizes.back() != 0 && "Unexpected zero size in Sizes.");
577 Sizes.back() = 1;
578
579 for (unsigned I = 0; I + 1 < Sizes.size(); I++) {
580 uint64_t PrevSize = Sizes[I + 1];
581 if (Sizes[I] % PrevSize) {
582 Sizes.clear();
583 return false;
584 }
585 Sizes[I] /= PrevSize;
586 }
587
588 // Finally, the last element in Sizes should be ElementSize.
589 Sizes.back() = *ElementSizeConst;
590 return true;
591}
592
593/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
594/// sizes of an array access, assuming that the array is a fixed size array.
595///
596/// E.g., if we have the code like as follows:
597///
598/// double A[42][8][32];
599/// for i
600/// for j
601/// for k
602/// use A[i][j][k]
603///
604/// The access function will be represented as an AddRec SCEV like:
605///
606/// AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
607///
608/// Then findFixedSizeArrayDimensions infers the size of each dimension of the
609/// array based on the fact that the value of the step recurrence is a multiple
610/// of the size of the corresponding array element. In the above example, it
611/// results in the following:
612///
613/// CHECK: ArrayDecl[UnknownSize][8][32] with elements of 8 bytes.
614///
615/// Finally each subscript will be computed as follows:
616///
617/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
618///
619/// Note that this function doesn't check the range of possible values for each
620/// subscript, so the caller should perform additional boundary checks if
621/// necessary.
622///
623/// Also note that this function doesn't guarantee that the original array size
624/// is restored "correctly". For example, in the following case:
625///
626/// double A[42][4][64];
627/// double B[42][8][32];
628/// for i
629/// for j
630/// for k
631/// use A[i][j][k]
632/// use B[i][2*j][k]
633///
634/// The access function for both accesses will be the same:
635///
636/// AddRec: {{{0,+,2048}<%for.i>,+,512}<%for.j>,+,8}<%for.k> (ElementSize=8)
637///
638/// The array sizes for both A and B will be computed as
639/// ArrayDecl[UnknownSize][4][64], which matches for A, but not for B.
640///
641/// TODO: At the moment, this function can handle only simple cases. For
642/// example, we cannot handle a case where a step recurrence is not divisible
643/// by the next smaller step recurrence, e.g., A[i][3*j].
647 const SCEV *ElementSize) {
648 // Clear output vectors.
649 Subscripts.clear();
650 Sizes.clear();
651
652 // First step: find the fixed array size.
653 SmallVector<uint64_t, 4> ConstSizes;
654 if (!findFixedSizeArrayDimensions(SE, Expr, ConstSizes, ElementSize)) {
655 Sizes.clear();
656 return false;
657 }
658
659 // Convert the constant size to SCEV.
660 for (uint64_t Size : ConstSizes)
661 Sizes.push_back(SE.getConstant(Expr->getType(), Size));
662
663 // Second step: compute the access functions for each subscript.
664 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
665
666 return !Subscripts.empty();
667}
668
669static bool isKnownNonNegative(ScalarEvolution *SE, const SCEV *S,
670 const Value *Ptr) {
671 bool Inbounds = false;
672 if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(Ptr))
673 Inbounds = SrcGEP->isInBounds();
674 if (Inbounds) {
675 if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
676 if (AddRec->isAffine()) {
677 // We know S is for Ptr, the operand on a load/store, so doesn't wrap.
678 // If both parts are NonNegative, the end result will be NonNegative
679 if (SE->isKnownNonNegative(AddRec->getStart()) &&
680 SE->isKnownNonNegative(AddRec->getOperand(1)))
681 return true;
682 }
683 }
684 }
685
686 return SE->isKnownNonNegative(S);
687}
688
689/// Compare to see if S is less than Size, using
690///
691/// isKnownNegative(S - Size)
692///
693/// with some extra checking if S is an AddRec and we can prove less-than using
694/// the loop bounds.
695static bool isKnownLessThan(ScalarEvolution *SE, const SCEV *S,
696 const SCEV *Size) {
697 // First unify to the same type
698 auto *SType = dyn_cast<IntegerType>(S->getType());
699 auto *SizeType = dyn_cast<IntegerType>(Size->getType());
700 if (!SType || !SizeType)
701 return false;
702 Type *MaxType =
703 (SType->getBitWidth() >= SizeType->getBitWidth()) ? SType : SizeType;
704 S = SE->getTruncateOrZeroExtend(S, MaxType);
705 Size = SE->getTruncateOrZeroExtend(Size, MaxType);
706
707 auto CollectUpperBound = [&](const Loop *L, Type *T) -> const SCEV * {
709 const SCEV *UB = SE->getBackedgeTakenCount(L);
710 return SE->getTruncateOrZeroExtend(UB, T);
711 }
712 return nullptr;
713 };
714
715 auto CheckAddRecBECount = [&]() {
716 const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S);
717 if (!AddRec || !AddRec->isAffine() || !AddRec->hasNoSignedWrap())
718 return false;
719 const SCEV *BECount = CollectUpperBound(AddRec->getLoop(), MaxType);
720 // If the BTC cannot be computed, check the base case for S.
721 if (!BECount || isa<SCEVCouldNotCompute>(BECount))
722 return false;
723 const SCEV *Start = AddRec->getStart();
724 const SCEV *Step = AddRec->getStepRecurrence(*SE);
725 const SCEV *End = AddRec->evaluateAtIteration(BECount, *SE);
726 const SCEV *Diff0 = SE->getMinusSCEV(Start, Size);
727 const SCEV *Diff1 = SE->getMinusSCEV(End, Size);
728
729 // If the value of Step is non-negative and the AddRec is non-wrap, it
730 // reaches its maximum at the last iteration. So it's enouth to check
731 // whether End - Size is negative.
732 if (SE->isKnownNonNegative(Step) && SE->isKnownNegative(Diff1))
733 return true;
734
735 // If the value of Step is non-positive and the AddRec is non-wrap, the
736 // initial value is its maximum.
737 if (SE->isKnownNonPositive(Step) && SE->isKnownNegative(Diff0))
738 return true;
739
740 // Even if we don't know the sign of Step, either Start or End must be
741 // the maximum value of the AddRec since it is non-wrap.
742 if (SE->isKnownNegative(Diff0) && SE->isKnownNegative(Diff1))
743 return true;
744
745 return false;
746 };
747
748 if (CheckAddRecBECount())
749 return true;
750
751 // Check using normal isKnownNegative
752 const SCEV *LimitedBound = SE->getMinusSCEV(S, Size);
753 return SE->isKnownNegative(LimitedBound);
754}
755
758 ArrayRef<const SCEV *> Subscripts,
759 const Value *Ptr) {
760 // Sizes and Subscripts are as follows:
761 //
762 // Sizes: [UNK][S_2]...[S_n]
763 // Subscripts: [I_1][I_2]...[I_n]
764 //
765 // where the size of the outermost dimension is unknown (UNK).
766
767 auto AddOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
768 if (!SE.willNotOverflow(Instruction::Add, /*IsSigned=*/true, A, B))
769 return nullptr;
770 return SE.getAddExpr(A, B);
771 };
772
773 auto MulOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
774 if (!SE.willNotOverflow(Instruction::Mul, /*IsSigned=*/true, A, B))
775 return nullptr;
776 return SE.getMulExpr(A, B);
777 };
778
779 // Range check: 0 <= I_k < S_k for k = 2..n.
780 for (size_t I = 1; I < Sizes.size(); ++I) {
781 const SCEV *Size = Sizes[I - 1];
782 const SCEV *Subscript = Subscripts[I];
783 if (!isKnownNonNegative(&SE, Subscript, Ptr))
784 return false;
785 if (!isKnownLessThan(&SE, Subscript, Size))
786 return false;
787 }
788
789 // The offset computation is as follows:
790 //
791 // Offset = I_n +
792 // S_n * I_{n-1} +
793 // ... +
794 // (S_2 * ... * S_n) * I_1
795 //
796 // Regarding this as a function from (I_1, I_2, ..., I_n) to integers, it
797 // must be injective. To guarantee it, the above calculation must not
798 // overflow. Since we have already checked that 0 <= I_k < S_k for k = 2..n,
799 // the minimum and maximum values occur in the following cases:
800 //
801 // Min = [I_1][0]...[0] = S_2 * ... * S_n * I_1
802 // Max = [I_1][S_2-1]...[S_n-1]
803 // = (S_2 * ... * S_n) * I_1 +
804 // (S_2 * ... * S_{n-1}) * (S_2 - 1) +
805 // ... +
806 // (S_n - 1)
807 // = (S_2 * ... * S_n) * I_1 +
808 // (S_2 * ... * S_n) - 1 (can be proven by induction)
809 // = Min + (S_2 * ... * S_n) - 1
810 //
811 // NOTE: I_1 can be negative, so Min is not just 0.
812 const SCEV *Prod = SE.getOne(Sizes[0]->getType());
813 for (const SCEV *Size : Sizes) {
814 Prod = MulOverflow(Prod, Size);
815 if (!Prod)
816 return false;
817 }
818 const SCEV *Min = MulOverflow(Prod, Subscripts[0]);
819 if (!Min)
820 return false;
821
822 // We have already checked that Min and Prod don't overflow, so it's enough
823 // to check whether Min + Prod - 1 doesn't overflow.
824 const SCEV *MaxPlusOne = AddOverflow(Min, Prod);
825 if (!MaxPlusOne)
826 return false;
827 if (!SE.willNotOverflow(Instruction::Sub, /*IsSigned=*/true, MaxPlusOne,
828 SE.getOne(MaxPlusOne->getType())))
829 return false;
830
831 return true;
832}
833
835 const GetElementPtrInst *GEP,
838 assert(Subscripts.empty() && Sizes.empty() &&
839 "Expected output lists to be empty on entry to this function.");
840 assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
841 LLVM_DEBUG(dbgs() << "\nGEP to delinearize: " << *GEP << "\n");
842 Type *Ty = nullptr;
843 Type *IndexTy = SE.getEffectiveSCEVType(GEP->getPointerOperandType());
844 bool DroppedFirstDim = false;
845 for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
846 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
847 if (i == 1) {
848 Ty = GEP->getSourceElementType();
849 if (auto *Const = dyn_cast<SCEVConstant>(Expr))
850 if (Const->getValue()->isZero()) {
851 DroppedFirstDim = true;
852 continue;
853 }
854 Subscripts.push_back(Expr);
855 continue;
856 }
857
858 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
859 if (!ArrayTy) {
860 LLVM_DEBUG(dbgs() << "GEP delinearize failed: " << *Ty
861 << " is not an array type.\n");
862 Subscripts.clear();
863 Sizes.clear();
864 return false;
865 }
866
867 Subscripts.push_back(Expr);
868 if (!(DroppedFirstDim && i == 2))
869 Sizes.push_back(SE.getConstant(IndexTy, ArrayTy->getNumElements()));
870
871 Ty = ArrayTy->getElementType();
872 }
873 LLVM_DEBUG({
874 dbgs() << "Subscripts:\n";
875 for (const SCEV *S : Subscripts)
876 dbgs() << *S << "\n";
877 dbgs() << "\n";
878 });
879
880 return !Subscripts.empty();
881}
882
883namespace {
884
885void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
886 ScalarEvolution *SE) {
887 O << "Printing analysis 'Delinearization' for function '" << F->getName()
888 << "':";
889 for (Instruction &Inst : instructions(F)) {
890 // Only analyze loads and stores.
891 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst))
892 continue;
893
894 const BasicBlock *BB = Inst.getParent();
895 Loop *L = LI->getLoopFor(BB);
896 // Only delinearize the memory access in the innermost loop.
897 // Do not analyze memory accesses outside loops.
898 if (!L)
899 continue;
900
901 const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
902
903 const SCEVUnknown *BasePointer =
905 // Do not delinearize if we cannot find the base pointer.
906 if (!BasePointer)
907 break;
908 AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
909
910 O << "\n";
911 O << "Inst:" << Inst << "\n";
912 O << "AccessFunction: " << *AccessFn << "\n";
913
914 SmallVector<const SCEV *, 3> Subscripts, Sizes;
915
916 auto IsDelinearizationFailed = [&]() {
917 return Subscripts.size() == 0 || Sizes.size() == 0 ||
918 Subscripts.size() != Sizes.size();
919 };
920
921 delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
922 if (UseFixedSizeArrayHeuristic && IsDelinearizationFailed()) {
923 Subscripts.clear();
924 Sizes.clear();
925 delinearizeFixedSizeArray(*SE, AccessFn, Subscripts, Sizes,
926 SE->getElementSize(&Inst));
927 }
928
929 if (IsDelinearizationFailed()) {
930 O << "failed to delinearize\n";
931 continue;
932 }
933
934 O << "Base offset: " << *BasePointer << "\n";
935 O << "ArrayDecl[UnknownSize]";
936 int Size = Subscripts.size();
937 for (int i = 0; i < Size - 1; i++)
938 O << "[" << *Sizes[i] << "]";
939 O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
940
941 O << "ArrayRef";
942 for (int i = 0; i < Size; i++)
943 O << "[" << *Subscripts[i] << "]";
944 O << "\n";
945
946 bool IsValid = validateDelinearizationResult(
947 *SE, Sizes, Subscripts, getLoadStorePointerOperand(&Inst));
948 O << "Delinearization validation: " << (IsValid ? "Succeeded" : "Failed")
949 << "\n";
950 }
951}
952
953} // end anonymous namespace
954
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 bool isKnownLessThan(ScalarEvolution *SE, const SCEV *S, const SCEV *Size)
Compare to see if S is less than Size, using.
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)
Hexagon Common GEP
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
#define LLVM_DEBUG(...)
Definition Debug.h:114
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
Class for arbitrary precision integers.
Definition APInt.h:78
std::optional< uint64_t > tryZExtValue() const
Get zero extended value if possible.
Definition APInt.h:1553
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
Definition APInt.cpp:1758
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:569
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.
LLVM_ABI const SCEV * evaluateAtIteration(const SCEV *It, ScalarEvolution &SE) const
Return the value of this chain of recurrences at the specified iteration number.
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 bool isKnownNonNegative(const SCEV *S)
Test if the given expression is known to be non-negative.
LLVM_ABI bool isKnownNonPositive(const SCEV *S)
Test if the given expression is known to be non-positive.
LLVM_ABI bool isKnownNegative(const SCEV *S)
Test if the given expression is known to be negative.
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 * getBackedgeTakenCount(const Loop *L, ExitCountKind Kind=Exact)
If the specified loop has a predictable backedge-taken count, return it, otherwise return a SCEVCould...
LLVM_ABI bool willNotOverflow(Instruction::BinaryOps BinOp, bool Signed, const SCEV *LHS, const SCEV *RHS, const Instruction *CtxI=nullptr)
Is operation BinOp between LHS and RHS provably does not have a signed/unsigned overflow (Signed)?
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.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI Type * getEffectiveSCEVType(Type *Ty) const
Return a type with the same bitwidth as the given type and which represents how SCEV will treat the g...
LLVM_ABI const SCEV * getMinusSCEV(const SCEV *LHS, const SCEV *RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI bool hasLoopInvariantBackedgeTakenCount(const Loop *L)
Return true if the specified loop has an analyzable loop-invariant backedge-taken count.
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.
LLVM_ABI const SCEV * getTruncateOrZeroExtend(const SCEV *V, Type *Ty, unsigned Depth=0)
Return a SCEV corresponding to a conversion of the input value to the specified type.
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void visitAll(const SCEV *Root, SV &Visitor)
Use SCEVTraversal to visit all nodes in the given expression tree.
std::enable_if_t< std::is_signed_v< T >, T > MulOverflow(T X, T Y, T &Result)
Multiply two signed integers, computing the two's complement truncated result, returning true if an o...
Definition MathExtras.h:753
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...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:2088
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:1634
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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
@ Mul
Product of integers.
DWARFExpression::Operation Op
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:2132
std::enable_if_t< std::is_signed_v< T >, T > AddOverflow(T X, T Y, T &Result)
Add two signed integers, computing the two's complement truncated result, returning true if overflow ...
Definition MathExtras.h:701
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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:1594
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts, const Value *Ptr=nullptr)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
LLVM_ABI bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Returns true if the give value is known to be non-negative.
bool getIndexExpressionsFromGEP(ScalarEvolution &SE, const GetElementPtrInst *GEP, SmallVectorImpl< const SCEV * > &Subscripts, SmallVectorImpl< const SCEV * > &Sizes)
Gathers the individual index expressions from a GEP instruction.
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.