[llvm] [LoopInterchange] Relax the legality check to accept more patterns (PR #118267)
Ryotaro Kasuga via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 30 01:26:05 PST 2025
================
@@ -199,35 +208,128 @@ static void interChangeDependencies(CharMatrix &DepMatrix, unsigned FromIndx,
std::swap(DepMatrix[I][ToIndx], DepMatrix[I][FromIndx]);
}
-// After interchanging, check if the direction vector is valid.
-// [Theorem] A permutation of the loops in a perfect nest is legal if and only
-// if the direction matrix, after the same permutation is applied to its
-// columns, has no ">" direction as the leftmost non-"=" direction in any row.
-static bool isLexicographicallyPositive(std::vector<char> &DV) {
- for (unsigned char Direction : DV) {
- if (Direction == '<')
+// Classify the direction vector into the four patterns. The target vector is
+// [DV[Left], DV[Left+1], ..., DV[Right-1]], not the whole of \p DV.
+static DirectionVectorPattern
+classifyDirectionVector(const std::vector<char> &DV, unsigned Left,
+ unsigned Right) {
+ assert(Left <= Right && "Left must be less or equal to Right");
+ for (unsigned I = Left; I < Right; I++) {
+ unsigned char Direction = DV[I];
+ switch (Direction) {
+ case '<':
+ return DirectionVectorPattern::Positive;
+ case '>':
+ return DirectionVectorPattern::Negative;
+ case '*':
+ return DirectionVectorPattern::All;
+ case '=':
+ case 'I':
+ break;
+ default:
+ llvm_unreachable("Unknown element in direction vector");
+ }
+ }
+ return DirectionVectorPattern::Zero;
+}
+
+// Check whether the requested interchange is legal or not. The interchange is
+// valid if the following condition holds:
+//
+// [Cond] For two instructions that can access the same location, the execution
+// order of the instructions before and after interchanged is the same.
+//
+// If the direction vector doesn't contain '*', the above Cond is equivalent to
+// one of the following:
+//
+// - The leftmost non-'=' element is '<' before and after interchanging.
+// - The leftmost non-'=' element is '>' before and after interchanging.
+// - All the elements in the direction vector is '='.
+//
+// As for '*', we must treat it as having dependency in all directions. It could
+// be '<', it could be '>', it could be '='. We can eliminate '*'s from the
+// direction vector by enumerating all possible patterns by replacing '*' with
+// '<' or '>' or '=', and then doing the above checks for all of them. The
+// enumeration can grow exponentially, so it is not practical to run it as it
+// is. Fortunately, we can perform the following pruning.
+//
+// - For '*' to the left of \p OuterLoopId, replacing it with '=' is allowed.
+//
+// This is because, for patterns where '<' (or '>') is assigned to some '*' to
+// the left of \p OuterLoopId, the first (or second) condition above holds
+// regardless of interchanging. After doing this pruning, the interchange is
+// legal if the leftmost non-'=' element is the same before and after swapping
+// the element of \p OuterLoopId and \p InnerLoopId.
+//
+//
+// Example: Consider the following loop.
+//
+// ```
+// for (i=0; i<=32; i++)
+// for (j=0; j<N-1; j++)
+// for (k=0; k<N-1; k++) {
+// Src: A[i][j][k] = ...;
+// Dst: use(A[32-i][j+1][k+1]);
+// }
+// ```
+//
+// In this case, the direction vector is [* < <] (if the analysis is powerful
+// enough). The enumeration of all possible patterns by replacing '*' is as
+// follows:
+//
+// - [< < <] : when i < 16
+// - [= < <] : when i = 16
+// - [> < <] : when i > 16
+//
+// We can prove that it is safe to interchange the innermost two loops here,
+// because the interchange doesn't change the leftmost non-'=' element for all
+// enumerated vectors.
+//
+// TODO: There are cases where the interchange is legal but rejected. At least
+// the following patterns are legal:
+// - If both Dep[OuterLoopId] and Dep[InnerLoopId] are '=', the interchange is
+// legal regardless of any other elements.
+// - If the loops are adjacent to each other and at least one of them is '=',
+// the interchange is legal even if the other is '*'.
----------------
kasuga-fj wrote:
I think it would be better to separate the PR, so I left it as a TODO. As I tested on my local, addressing these items makes some tests pass that are marked as XFAIL in #119345 .
https://github.com/llvm/llvm-project/pull/118267
More information about the llvm-commits
mailing list