LLVM 23.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.
11//
12//===----------------------------------------------------------------------===//
13
19#include "llvm/IR/Constants.h"
21#include "llvm/IR/Function.h"
24#include "llvm/IR/PassManager.h"
26#include "llvm/Support/Debug.h"
28
29using namespace llvm;
30
31#define DL_NAME "delinearize"
32#define DEBUG_TYPE DL_NAME
33
35 "delinearize-use-fixed-size-array-heuristic", cl::init(true), cl::Hidden,
36 cl::desc("When printing analysis, use the heuristic for fixed-size arrays "
37 "if the default delinearizetion fails."));
38
39// Return true when S contains at least an undef value.
40static inline bool containsUndefs(const SCEV *S) {
41 return SCEVExprContains(S, [](const SCEV *S) {
42 if (const auto *SU = dyn_cast<SCEVUnknown>(S))
43 return isa<UndefValue>(SU->getValue());
44 return false;
45 });
46}
47
48namespace {
49
50// Collect all steps of SCEV expressions.
51struct SCEVCollectStrides {
52 ScalarEvolution &SE;
53 SmallVectorImpl<const SCEV *> &Strides;
54
55 SCEVCollectStrides(ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &S)
56 : SE(SE), Strides(S) {}
57
58 bool follow(const SCEV *S) {
59 if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S))
60 Strides.push_back(AR->getStepRecurrence(SE));
61 return true;
62 }
63
64 bool isDone() const { return false; }
65};
66
67// Collect all SCEVUnknown and SCEVMulExpr expressions.
68struct SCEVCollectTerms {
69 SmallVectorImpl<const SCEV *> &Terms;
70
71 SCEVCollectTerms(SmallVectorImpl<const SCEV *> &T) : Terms(T) {}
72
73 bool follow(const SCEV *S) {
76 if (!containsUndefs(S))
77 Terms.push_back(S);
78
79 // Stop recursion: once we collected a term, do not walk its operands.
80 return false;
81 }
82
83 // Keep looking.
84 return true;
85 }
86
87 bool isDone() const { return false; }
88};
89
90// Check if a SCEV contains an AddRecExpr.
91struct SCEVHasAddRec {
92 bool &ContainsAddRec;
93
94 SCEVHasAddRec(bool &ContainsAddRec) : ContainsAddRec(ContainsAddRec) {
95 ContainsAddRec = false;
96 }
97
98 bool follow(const SCEV *S) {
99 if (isa<SCEVAddRecExpr>(S)) {
100 ContainsAddRec = true;
101
102 // Stop recursion: once we collected a term, do not walk its operands.
103 return false;
104 }
105
106 // Keep looking.
107 return true;
108 }
109
110 bool isDone() const { return false; }
111};
112
113// Find factors that are multiplied with an expression that (possibly as a
114// subexpression) contains an AddRecExpr. In the expression:
115//
116// 8 * (100 + %p * %q * (%a + {0, +, 1}_loop))
117//
118// "%p * %q" are factors multiplied by the expression "(%a + {0, +, 1}_loop)"
119// that contains the AddRec {0, +, 1}_loop. %p * %q are likely to be array size
120// parameters as they form a product with an induction variable.
121//
122// This collector expects all array size parameters to be in the same MulExpr.
123// It might be necessary to later add support for collecting parameters that are
124// spread over different nested MulExpr.
125struct SCEVCollectAddRecMultiplies {
126 SmallVectorImpl<const SCEV *> &Terms;
127 ScalarEvolution &SE;
128
129 SCEVCollectAddRecMultiplies(SmallVectorImpl<const SCEV *> &T,
130 ScalarEvolution &SE)
131 : Terms(T), SE(SE) {}
132
133 bool follow(const SCEV *S) {
134 if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
135 bool HasAddRec = false;
137 for (const SCEV *Op : Mul->operands()) {
138 const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
139 if (Unknown && !isa<CallInst>(Unknown->getValue())) {
140 Operands.push_back(Op);
141 } else if (Unknown) {
142 HasAddRec = true;
143 } else {
144 bool ContainsAddRec = false;
145 SCEVHasAddRec ContiansAddRec(ContainsAddRec);
146 visitAll(Op, ContiansAddRec);
147 HasAddRec |= ContainsAddRec;
148 }
149 }
150 if (Operands.size() == 0)
151 return true;
152
153 if (!HasAddRec)
154 return false;
155
156 Terms.push_back(SE.getMulExpr(Operands));
157 // Stop recursion: once we collected a term, do not walk its operands.
158 return false;
159 }
160
161 // Keep looking.
162 return true;
163 }
164
165 bool isDone() const { return false; }
166};
167
168} // end anonymous namespace
169
170/// Find parametric terms in this SCEVAddRecExpr. We first for parameters in
171/// two places:
172/// 1) The strides of AddRec expressions.
173/// 2) Unknowns that are multiplied with AddRec expressions.
177 SCEVCollectStrides StrideCollector(SE, Strides);
178 visitAll(Expr, StrideCollector);
179
180 LLVM_DEBUG({
181 dbgs() << "Strides:\n";
182 for (const SCEV *S : Strides)
183 dbgs().indent(2) << *S << "\n";
184 });
185
186 for (const SCEV *S : Strides) {
187 SCEVCollectTerms TermCollector(Terms);
188 visitAll(S, TermCollector);
189 }
190
191 LLVM_DEBUG({
192 dbgs() << "Terms:\n";
193 for (const SCEV *T : Terms)
194 dbgs().indent(2) << *T << "\n";
195 });
196
197 SCEVCollectAddRecMultiplies MulCollector(Terms, SE);
198 visitAll(Expr, MulCollector);
199}
200
204 int Last = Terms.size() - 1;
205 const SCEV *Step = Terms[Last];
206
207 // End of recursion.
208 if (Last == 0) {
209 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
211 for (const SCEV *Op : M->operands())
212 if (!isa<SCEVConstant>(Op))
213 Qs.push_back(Op);
214
215 Step = SE.getMulExpr(Qs);
216 }
217
218 Sizes.push_back(Step);
219 return true;
220 }
221
222 for (const SCEV *&Term : Terms) {
223 // Normalize the terms before the next call to findArrayDimensionsRec.
224 const SCEV *Q, *R;
225 SCEVDivision::divide(SE, Term, Step, &Q, &R);
226
227 // Bail out when GCD does not evenly divide one of the terms.
228 if (!R->isZero())
229 return false;
230
231 Term = Q;
232 }
233
234 // Remove all SCEVConstants.
235 erase_if(Terms, [](const SCEV *E) { return isa<SCEVConstant>(E); });
236
237 if (Terms.size() > 0)
238 if (!findArrayDimensionsRec(SE, Terms, Sizes))
239 return false;
240
241 Sizes.push_back(Step);
242 return true;
243}
244
245// Returns true when one of the SCEVs of Terms contains a SCEVUnknown parameter.
247 for (const SCEV *T : Terms)
248 if (SCEVExprContains(T, [](const SCEV *S) { return isa<SCEVUnknown>(S); }))
249 return true;
250
251 return false;
252}
253
254// Return the number of product terms in S.
255static inline int numberOfTerms(const SCEV *S) {
256 if (const SCEVMulExpr *Expr = dyn_cast<SCEVMulExpr>(S))
257 return Expr->getNumOperands();
258 return 1;
259}
260
261static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
262 if (isa<SCEVConstant>(T))
263 return nullptr;
264
265 if (isa<SCEVUnknown>(T))
266 return T;
267
268 if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
270 for (const SCEV *Op : M->operands())
271 if (!isa<SCEVConstant>(Op))
272 Factors.push_back(Op);
273
274 return SE.getMulExpr(Factors);
275 }
276
277 return T;
278}
279
283 const SCEV *ElementSize) {
284 if (Terms.size() < 1 || !ElementSize)
285 return;
286
287 // Early return when Terms do not contain parameters: we do not delinearize
288 // non parametric SCEVs.
289 if (!containsParameters(Terms))
290 return;
291
292 LLVM_DEBUG({
293 dbgs() << "Terms:\n";
294 for (const SCEV *T : Terms)
295 dbgs().indent(2) << *T << "\n";
296 });
297
298 // Remove duplicates.
299 array_pod_sort(Terms.begin(), Terms.end());
300 Terms.erase(llvm::unique(Terms), Terms.end());
301
302 // Put larger terms first.
303 llvm::sort(Terms, [](const SCEV *LHS, const SCEV *RHS) {
304 return numberOfTerms(LHS) > numberOfTerms(RHS);
305 });
306
307 // Try to divide all terms by the element size. If term is not divisible by
308 // element size, proceed with the original term.
309 for (const SCEV *&Term : Terms) {
310 const SCEV *Q, *R;
311 SCEVDivision::divide(SE, Term, ElementSize, &Q, &R);
312 if (!Q->isZero())
313 Term = Q;
314 }
315
317
318 // Remove constant factors.
319 for (const SCEV *T : Terms)
320 if (const SCEV *NewT = removeConstantFactors(SE, T))
321 NewTerms.push_back(NewT);
322
323 LLVM_DEBUG({
324 dbgs() << "Terms after sorting:\n";
325 for (const SCEV *T : NewTerms)
326 dbgs().indent(2) << *T << "\n";
327 });
328
329 if (NewTerms.empty() || !findArrayDimensionsRec(SE, NewTerms, Sizes)) {
330 Sizes.clear();
331 return;
332 }
333
334 // The last element to be pushed into Sizes is the size of an element.
335 Sizes.push_back(ElementSize);
336
337 LLVM_DEBUG({
338 dbgs() << "Sizes:\n";
339 for (const SCEV *S : Sizes)
340 dbgs().indent(2) << *S << "\n";
341 });
342}
343
347 // Early exit in case this SCEV is not an affine multivariate function.
348 if (Sizes.empty())
349 return;
350
351 if (auto *AR = dyn_cast<SCEVAddRecExpr>(Expr))
352 if (!AR->isAffine())
353 return;
354
355 // Clear output vector.
356 Subscripts.clear();
357
358 LLVM_DEBUG(dbgs() << "\ncomputeAccessFunctions\n"
359 << "Memory Access Function: " << *Expr << "\n");
360
361 const SCEV *Res = Expr;
362 int Last = Sizes.size() - 1;
363
364 for (int i = Last; i >= 0; i--) {
365 const SCEV *Size = Sizes[i];
366 const SCEV *Q, *R;
367
368 SCEVDivision::divide(SE, Res, Size, &Q, &R);
369
370 LLVM_DEBUG({
371 dbgs() << "Computing 'MemAccFn / Sizes[" << i << "]':\n";
372 dbgs() << " MemAccFn: " << *Res << "\n";
373 dbgs() << " Sizes[" << i << "]: " << *Size << "\n";
374 dbgs() << " Quotient (Leftover): " << *Q << "\n";
375 dbgs() << " Remainder (Subscript Access Function): " << *R << "\n";
376 });
377
378 Res = Q;
379
380 // Do not record the last subscript corresponding to the size of elements in
381 // the array.
382 if (i == Last) {
383
384 // Bail out if the byte offset is non-zero.
385 if (!R->isZero()) {
386 Subscripts.clear();
387 Sizes.clear();
388 return;
389 }
390
391 continue;
392 }
393
394 // Record the access function for the current subscript.
395 Subscripts.push_back(R);
396 }
397
398 // Also push in last position the remainder of the last division: it will be
399 // the access function of the innermost dimension.
400 Subscripts.push_back(Res);
401
402 std::reverse(Subscripts.begin(), Subscripts.end());
403
404 LLVM_DEBUG({
405 dbgs() << "Subscripts:\n";
406 for (const SCEV *S : Subscripts)
407 dbgs().indent(2) << *S << "\n";
408 dbgs() << "\n";
409 });
410}
411
412/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
413/// sizes of an array access. Returns the remainder of the delinearization that
414/// is the offset start of the array. The SCEV->delinearize algorithm computes
415/// the multiples of SCEV coefficients: that is a pattern matching of sub
416/// expressions in the stride and base of a SCEV corresponding to the
417/// computation of a GCD (greatest common divisor) of base and stride. When
418/// SCEV->delinearize fails, it returns the SCEV unchanged.
419///
420/// For example: when analyzing the memory access A[i][j][k] in this loop nest
421///
422/// void foo(long n, long m, long o, double A[n][m][o]) {
423///
424/// for (long i = 0; i < n; i++)
425/// for (long j = 0; j < m; j++)
426/// for (long k = 0; k < o; k++)
427/// A[i][j][k] = 1.0;
428/// }
429///
430/// the delinearization input is the following AddRec SCEV:
431///
432/// AddRec: {{{%A,+,(8 * %m * %o)}<%for.i>,+,(8 * %o)}<%for.j>,+,8}<%for.k>
433///
434/// From this SCEV, we are able to say that the base offset of the access is %A
435/// because it appears as an offset that does not divide any of the strides in
436/// the loops:
437///
438/// CHECK: Base offset: %A
439///
440/// and then SCEV->delinearize determines the size of some of the dimensions of
441/// the array as these are the multiples by which the strides are happening:
442///
443/// CHECK: ArrayDecl[UnknownSize][%m][%o] with elements of sizeof(double)
444/// bytes.
445///
446/// Note that the outermost dimension remains of UnknownSize because there are
447/// no strides that would help identifying the size of the last dimension: when
448/// the array has been statically allocated, one could compute the size of that
449/// dimension by dividing the overall size of the array by the size of the known
450/// dimensions: %m * %o * 8.
451///
452/// Finally delinearize provides the access functions for the array reference
453/// that does correspond to A[i][j][k] of the above C testcase:
454///
455/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
456///
457/// The testcases are checking the output of a function pass:
458/// DelinearizationPass that walks through all loads and stores of a function
459/// asking for the SCEV of the memory access with respect to all enclosing
460/// loops, calling SCEV->delinearize on that and printing the results.
464 const SCEV *ElementSize) {
465 // Clear output vectors.
466 Subscripts.clear();
467 Sizes.clear();
468
469 // First step: collect parametric terms.
471 collectParametricTerms(SE, Expr, Terms);
472
473 if (Terms.empty())
474 return;
475
476 // Second step: find subscript sizes.
477 findArrayDimensions(SE, Terms, Sizes, ElementSize);
478
479 if (Sizes.empty())
480 return;
481
482 // Third step: compute the access functions for each subscript.
483 computeAccessFunctions(SE, Expr, Subscripts, Sizes);
484}
485
486static std::optional<APInt> tryIntoAPInt(const SCEV *S) {
487 if (const auto *Const = dyn_cast<SCEVConstant>(S))
488 return Const->getAPInt();
489 return std::nullopt;
490}
491
492/// Collects the absolute values of constant steps for all induction variables.
493/// Returns true if we can prove that all step recurrences are constants and \p
494/// Expr is divisible by \p ElementSize. Each step recurrence is stored in \p
495/// Steps after divided by \p ElementSize.
496static bool collectConstantAbsSteps(ScalarEvolution &SE, const SCEV *Expr,
498 uint64_t ElementSize) {
499 // End of recursion. The constant value also must be a multiple of
500 // ElementSize.
501 if (const auto *Const = dyn_cast<SCEVConstant>(Expr)) {
502 const uint64_t Mod = Const->getAPInt().urem(ElementSize);
503 return Mod == 0;
504 }
505
507 if (!AR || !AR->isAffine())
508 return false;
509
510 const SCEV *Step = AR->getStepRecurrence(SE);
511 std::optional<APInt> StepAPInt = tryIntoAPInt(Step);
512 if (!StepAPInt)
513 return false;
514
515 APInt Q;
516 uint64_t R;
517 APInt::udivrem(StepAPInt->abs(), ElementSize, Q, R);
518 if (R != 0)
519 return false;
520
521 // Bail out when the step is too large.
522 std::optional<uint64_t> StepVal = Q.tryZExtValue();
523 if (!StepVal)
524 return false;
525
526 Steps.push_back(*StepVal);
527 return collectConstantAbsSteps(SE, AR->getStart(), Steps, ElementSize);
528}
529
532 const SCEV *ElementSize) {
533 if (!ElementSize)
534 return false;
535
536 std::optional<APInt> ElementSizeAPInt = tryIntoAPInt(ElementSize);
537 if (!ElementSizeAPInt || *ElementSizeAPInt == 0)
538 return false;
539
540 std::optional<uint64_t> ElementSizeConst = ElementSizeAPInt->tryZExtValue();
541
542 // Early exit when ElementSize is not a positive constant.
543 if (!ElementSizeConst)
544 return false;
545
546 if (!collectConstantAbsSteps(SE, Expr, Sizes, *ElementSizeConst) ||
547 Sizes.empty()) {
548 Sizes.clear();
549 return false;
550 }
551
552 // At this point, Sizes contains the absolute step recurrences for all
553 // induction variables. Each step recurrence must be a multiple of the size of
554 // the array element. Assuming that the each value represents the size of an
555 // array for each dimension, attempts to restore the length of each dimension
556 // by dividing the step recurrence by the next smaller value. For example, if
557 // we have the following AddRec SCEV:
558 //
559 // AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
560 //
561 // Then Sizes will become [256, 32, 1] after sorted. We don't know the size of
562 // the outermost dimension, the next dimension will be computed as 256 / 32 =
563 // 8, and the last dimension will be computed as 32 / 1 = 32. Thus it results
564 // in like Arr[UnknownSize][8][32] with elements of size 8 bytes, where Arr is
565 // a base pointer.
566 //
567 // TODO: Catch more cases, e.g., when a step recurrence is not divisible by
568 // the next smaller one, like A[i][3*j].
569 llvm::sort(Sizes.rbegin(), Sizes.rend());
570 Sizes.erase(llvm::unique(Sizes), Sizes.end());
571
572 // The last element in Sizes should be ElementSize. At this point, all values
573 // in Sizes are assumed to be divided by ElementSize, so replace it with 1.
574 assert(Sizes.back() != 0 && "Unexpected zero size in Sizes.");
575 Sizes.back() = 1;
576
577 for (unsigned I = 0; I + 1 < Sizes.size(); I++) {
578 uint64_t PrevSize = Sizes[I + 1];
579 if (Sizes[I] % PrevSize) {
580 Sizes.clear();
581 return false;
582 }
583 Sizes[I] /= PrevSize;
584 }
585
586 // Finally, the last element in Sizes should be ElementSize.
587 Sizes.back() = *ElementSizeConst;
588 return true;
589}
590
591/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
592/// sizes of an array access, assuming that the array is a fixed size array.
593///
594/// E.g., if we have the code like as follows:
595///
596/// double A[42][8][32];
597/// for i
598/// for j
599/// for k
600/// use A[i][j][k]
601///
602/// The access function will be represented as an AddRec SCEV like:
603///
604/// AddRec: {{{0,+,2048}<%for.i>,+,256}<%for.j>,+,8}<%for.k> (ElementSize=8)
605///
606/// Then findFixedSizeArrayDimensions infers the size of each dimension of the
607/// array based on the fact that the value of the step recurrence is a multiple
608/// of the size of the corresponding array element. In the above example, it
609/// results in the following:
610///
611/// CHECK: ArrayDecl[UnknownSize][8][32] with elements of 8 bytes.
612///
613/// Finally each subscript will be computed as follows:
614///
615/// CHECK: ArrayRef[{0,+,1}<%for.i>][{0,+,1}<%for.j>][{0,+,1}<%for.k>]
616///
617/// Note that this function doesn't check the range of possible values for each
618/// subscript, so the caller should perform additional boundary checks if
619/// necessary.
620///
621/// Also note that this function doesn't guarantee that the original array size
622/// is restored "correctly". For example, in the following case:
623///
624/// double A[42][4][64];
625/// double B[42][8][32];
626/// for i
627/// for j
628/// for k
629/// use A[i][j][k]
630/// use B[i][2*j][k]
631///
632/// The access function for both accesses will be the same:
633///
634/// AddRec: {{{0,+,2048}<%for.i>,+,512}<%for.j>,+,8}<%for.k> (ElementSize=8)
635///
636/// The array sizes for both A and B will be computed as
637/// ArrayDecl[UnknownSize][4][64], which matches for A, but not for B.
638///
639/// TODO: At the moment, this function can handle only simple cases. For
640/// example, we cannot handle a case where a step recurrence is not divisible
641/// by the next smaller step recurrence, e.g., A[i][3*j].
645 const SCEV *ElementSize) {
646 // Clear output vectors.
647 Subscripts.clear();
648 Sizes.clear();
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
669 ArrayRef<const SCEV *> Subscripts) {
670 // Sizes and Subscripts are as follows:
671 //
672 // Sizes: [UNK][S_2]...[S_n]
673 // Subscripts: [I_1][I_2]...[I_n]
674 //
675 // where the size of the outermost dimension is unknown (UNK).
676
677 auto AddOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
678 if (!SE.willNotOverflow(Instruction::Add, /*IsSigned=*/true, A, B))
679 return nullptr;
680 return SE.getAddExpr(A, B);
681 };
682
683 auto MulOverflow = [&](const SCEV *A, const SCEV *B) -> const SCEV * {
684 if (!SE.willNotOverflow(Instruction::Mul, /*IsSigned=*/true, A, B))
685 return nullptr;
686 return SE.getMulExpr(A, B);
687 };
688
689 // Range check: 0 <= I_k < S_k for k = 2..n.
690 for (size_t I = 1; I < Sizes.size(); ++I) {
691 const SCEV *Size = Sizes[I - 1];
692 const SCEV *Subscript = Subscripts[I];
693 if (!SE.isKnownNonNegative(Subscript))
694 return false;
695
696 // TODO: It may be better that delinearization itself unifies the types of
697 // all elements in Sizes and Subscripts.
698 Type *WiderTy = SE.getWiderType(Subscript->getType(), Size->getType());
699 Subscript = SE.getNoopOrSignExtend(Subscript, WiderTy);
700 Size = SE.getNoopOrSignExtend(Size, WiderTy);
701 if (!SE.isKnownPredicate(ICmpInst::ICMP_SLT, Subscript, Size)) {
702 LLVM_DEBUG(dbgs() << "Range check failed: " << *Subscript << " <s "
703 << *Size << "\n");
704 return false;
705 }
706 }
707
708 // The offset computation is as follows:
709 //
710 // Offset = I_n +
711 // S_n * I_{n-1} +
712 // ... +
713 // (S_2 * ... * S_n) * I_1
714 //
715 // Regarding this as a function from (I_1, I_2, ..., I_n) to integers, it
716 // must be injective. To guarantee it, the above calculation must not
717 // overflow. Since we have already checked that 0 <= I_k < S_k for k = 2..n,
718 // the minimum and maximum values occur in the following cases:
719 //
720 // Min = [I_1][0]...[0] = S_2 * ... * S_n * I_1
721 // Max = [I_1][S_2-1]...[S_n-1]
722 // = (S_2 * ... * S_n) * I_1 +
723 // (S_2 * ... * S_{n-1}) * (S_2 - 1) +
724 // ... +
725 // (S_n - 1)
726 // = (S_2 * ... * S_n) * I_1 +
727 // (S_2 * ... * S_n) - 1 (can be proven by induction)
728 // = Min + (S_2 * ... * S_n) - 1
729 //
730 // NOTE: I_1 can be negative, so Min is not just 0.
731 const SCEV *Prod = SE.getOne(Sizes[0]->getType());
732 for (const SCEV *Size : Sizes) {
733 Prod = MulOverflow(Prod, Size);
734 if (!Prod)
735 return false;
736 }
737 const SCEV *Min = MulOverflow(Prod, Subscripts[0]);
738 if (!Min)
739 return false;
740
741 // We have already checked that Min and Prod don't overflow, so it's enough
742 // to check whether Min + Prod - 1 doesn't overflow.
743 const SCEV *MaxPlusOne = AddOverflow(Min, Prod);
744 if (!MaxPlusOne)
745 return false;
746 if (!SE.willNotOverflow(Instruction::Sub, /*IsSigned=*/true, MaxPlusOne,
747 SE.getOne(MaxPlusOne->getType())))
748 return false;
749
750 return true;
751}
752
754 const GetElementPtrInst *GEP,
757 assert(Subscripts.empty() && Sizes.empty() &&
758 "Expected output lists to be empty on entry to this function.");
759 assert(GEP && "getIndexExpressionsFromGEP called with a null GEP");
760 LLVM_DEBUG(dbgs() << "\nGEP to delinearize: " << *GEP << "\n");
761 Type *Ty = nullptr;
762 Type *IndexTy = SE.getEffectiveSCEVType(GEP->getPointerOperandType());
763 bool DroppedFirstDim = false;
764 for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
765 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
766 if (i == 1) {
767 Ty = GEP->getSourceElementType();
768 if (auto *Const = dyn_cast<SCEVConstant>(Expr))
769 if (Const->getValue()->isZero()) {
770 DroppedFirstDim = true;
771 continue;
772 }
773 Subscripts.push_back(Expr);
774 continue;
775 }
776
777 auto *ArrayTy = dyn_cast<ArrayType>(Ty);
778 if (!ArrayTy) {
779 LLVM_DEBUG(dbgs() << "GEP delinearize failed: " << *Ty
780 << " is not an array type.\n");
781 Subscripts.clear();
782 Sizes.clear();
783 return false;
784 }
785
786 Subscripts.push_back(Expr);
787 if (!(DroppedFirstDim && i == 2))
788 Sizes.push_back(SE.getConstant(IndexTy, ArrayTy->getNumElements()));
789
790 Ty = ArrayTy->getElementType();
791 }
792 LLVM_DEBUG({
793 dbgs() << "Subscripts:\n";
794 for (const SCEV *S : Subscripts)
795 dbgs() << *S << "\n";
796 dbgs() << "\n";
797 });
798
799 return !Subscripts.empty();
800}
801
802namespace {
803
804void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
805 ScalarEvolution *SE) {
806 O << "Printing analysis 'Delinearization' for function '" << F->getName()
807 << "':";
808 for (Instruction &Inst : instructions(F)) {
809 // Only analyze loads and stores.
810 if (!isa<StoreInst>(&Inst) && !isa<LoadInst>(&Inst))
811 continue;
812
813 const BasicBlock *BB = Inst.getParent();
814 Loop *L = LI->getLoopFor(BB);
815 // Only delinearize the memory access in the innermost loop.
816 // Do not analyze memory accesses outside loops.
817 if (!L)
818 continue;
819
820 const SCEV *AccessFn = SE->getSCEVAtScope(getPointerOperand(&Inst), L);
821
822 const SCEVUnknown *BasePointer =
824 // Do not delinearize if we cannot find the base pointer.
825 if (!BasePointer)
826 break;
827 AccessFn = SE->getMinusSCEV(AccessFn, BasePointer);
828
829 O << "\n";
830 O << "Inst:" << Inst << "\n";
831 O << "AccessFunction: " << *AccessFn << "\n";
832
833 SmallVector<const SCEV *, 3> Subscripts, Sizes;
834
835 auto IsDelinearizationFailed = [&]() {
836 return Subscripts.size() == 0 || Sizes.size() == 0 ||
837 Subscripts.size() != Sizes.size();
838 };
839
840 delinearize(*SE, AccessFn, Subscripts, Sizes, SE->getElementSize(&Inst));
841 if (UseFixedSizeArrayHeuristic && IsDelinearizationFailed()) {
842 Subscripts.clear();
843 Sizes.clear();
844 delinearizeFixedSizeArray(*SE, AccessFn, Subscripts, Sizes,
845 SE->getElementSize(&Inst));
846 }
847
848 if (IsDelinearizationFailed()) {
849 O << "failed to delinearize\n";
850 continue;
851 }
852
853 O << "Base offset: " << *BasePointer << "\n";
854 O << "ArrayDecl[UnknownSize]";
855 int Size = Subscripts.size();
856 for (int i = 0; i < Size - 1; i++)
857 O << "[" << *Sizes[i] << "]";
858 O << " with elements of " << *Sizes[Size - 1] << " bytes.\n";
859
860 O << "ArrayRef";
861 for (int i = 0; i < Size; i++)
862 O << "[" << *Subscripts[i] << "]";
863 O << "\n";
864
865 bool IsValid = validateDelinearizationResult(*SE, Sizes, Subscripts);
866 O << "Delinearization validation: " << (IsValid ? "Succeeded" : "Failed")
867 << "\n";
868 }
869}
870
871} // end anonymous namespace
872
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 cl::opt< bool > UseFixedSizeArrayHeuristic("delinearize-use-fixed-size-array-heuristic", cl::init(true), cl::Hidden, cl::desc("When printing analysis, use the heuristic for fixed-size arrays " "if the default delinearizetion fails."))
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 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:1567
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
Definition APInt.cpp:1769
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
@ ICMP_SLT
signed less than
Definition InstrTypes.h:705
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.
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 Type * getWiderType(Type *Ty1, Type *Ty2) const
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 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.
LLVM_ABI const SCEV * getNoopOrSignExtend(const SCEV *V, Type *Ty)
Return a SCEV corresponding to a conversion of the input value to the specified type.
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 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 * getAddExpr(SmallVectorImpl< const SCEV * > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, const SCEV *LHS, const SCEV *RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
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
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.
Definition Types.h:26
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
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2134
bool validateDelinearizationResult(ScalarEvolution &SE, ArrayRef< const SCEV * > Sizes, ArrayRef< const SCEV * > Subscripts)
Check that each subscript in Subscripts is within the corresponding size in Sizes.
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:1636
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:2192
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:1596
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.