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