You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Delinearization] Add function for fixed size array without relying on GEP
The existing functions `getIndexExpressionsFromGEP` and
`tryDelinearizeFixedSizeImpl` provide functionality to delinearize
memory accesses for fixed size array. They use the GEP source element
type in their optimization heuristics. However, driving optimization
heuristics based on GEP type information is not allowed.
This patch introduces a new function `delinearizeFixedSizeArray` to
remove them. This is an initial implementation that may not cover all
cases, but is intended to replace the existing function in the future.
// Early exit when ElementSize is not a positive constant.
546
+
if (!ElementSizeConst)
547
+
returnfalse;
548
+
549
+
if (!collectConstantAbsSteps(SE, Expr, Sizes, *ElementSizeConst) ||
550
+
Sizes.empty()) {
551
+
Sizes.clear();
552
+
returnfalse;
553
+
}
554
+
555
+
// At this point, Sizes contains the absolute step recurrences for all induction variables. Each step recurrence must be a multiple of the size of the array element. Assuming that the each value represents the size of an array for each dimension, attempts to restore the length of each dimension by dividing the step recurrence by the next smaller value. For example, if we have the following AddRec SCEV:
// Then Sizes will become [256, 32, 1] after sorted. We don't know the size of the outermost dimension, the next dimension will be computed as 256 / 32 = 8, and the last dimension will be computed as 32 / 1 = 32. Thus it results in like Arr[UnknownSize][8][32] with elements of size 8 bytes, where Arr is a base pointer.
560
+
//
561
+
// TODO: Catch more cases, e.g., when a step recurrence is not dividable by the next smaller one, like A[i][3*j].
562
+
llvm::sort(Sizes.rbegin(), Sizes.rend());
563
+
Sizes.erase(llvm::unique(Sizes), Sizes.end());
564
+
for (unsigned I = 0; I + 1 < Sizes.size(); I++) {
565
+
unsigned PrevSize = Sizes[I + 1];
566
+
if (Sizes[I] % PrevSize) {
567
+
Sizes.clear();
568
+
returnfalse;
569
+
}
570
+
Sizes[I] /= PrevSize;
571
+
}
572
+
573
+
// The last element should be ElementSize.
574
+
Sizes.back() = *ElementSizeConst;
575
+
returntrue;
576
+
}
577
+
578
+
/// Splits the SCEV into two vectors of SCEVs representing the subscripts and
579
+
/// sizes of an array access, assuming that the array is a fixed size array.
580
+
///
581
+
/// E.g., if we have the code like as follows:
582
+
///
583
+
/// double A[42][8][32];
584
+
/// for i
585
+
/// for j
586
+
/// for k
587
+
/// use A[i][j][k]
588
+
///
589
+
/// The access function will be represented as an AddRec SCEV like:
/// Then findFixedSizeArrayDimensions infers the size of each dimension of the array based on the fact that the value of the step recurrence is a multiple of the size of the corresponding array element. In the above example, it results in the following:
594
+
///
595
+
/// CHECK: ArrayDecl[UnknownSize][8][32] with elements of 8 bytes.
596
+
///
597
+
/// Finally each subscript will be computed as follows:
/// Note that this function doesn't check the range of possible values for each
602
+
/// subscript, so the caller should perform additional boundary checks if
603
+
/// necessary.
604
+
///
605
+
/// TODO: At the moment, this function can handle only simple cases. For example, we cannot handle a case where a step recurrence is not dividable by the next smaller step recurrence, e.g., A[i][3*j]. Furthermore, this function doesn't guarantee that the original array size is restored "correctly". For example, in the following case:
606
+
///
607
+
/// double A[42][4][32];
608
+
/// double B[42][8][64];
609
+
/// for i
610
+
/// for j
611
+
/// for k
612
+
/// use A[i][j][k]
613
+
/// use B[i][2*j][k]
614
+
///
615
+
/// The access function for both accesses will be the same:
0 commit comments