From bc145d6a4cb91e311af482d85fa2e7f91c29f200 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga Date: Fri, 9 May 2025 10:52:47 +0000 Subject: [PATCH 1/4] [LoopInterchange] Exit early in certain cases in legality check (NFC) The legality check in LoopInterchange allows two loops to be exchanged if all direction vectors are lexicographically positive (or zero) for both before and after the swap. The current implementation performs this routine naively. However, if a direction vector is lexicographically positive due to an element corresponding to a loop that is outside the given two loops (i.e., if there is an element `<` before the loops we are trying to interchange), then obviously it is also positive after exchanging them. For example, for a direction vector `[< < >]`, swapping the last two elements doesn't make it lexicographically negative because the first element is `<`. This patch adds an early exit logic for such cases. Note that this is only a small improvement on its own, but it's necessary to relax the legality check I'm working on. --- .../lib/Transforms/Scalar/LoopInterchange.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index fb7bc7c4be6c8..f6d1860e66e1a 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -231,18 +231,22 @@ static void interChangeDependencies(CharMatrix &DepMatrix, unsigned FromIndx, std::swap(DepMatrix[I][ToIndx], DepMatrix[I][FromIndx]); } -// After interchanging, check if the direction vector is valid. +// Check if a direction vector is lexicographically positive. Return true if it +// is positive, nullopt if it is "zero", othrewise false. // [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 &DV) { - for (unsigned char Direction : DV) { +static std::optional isLexicographicallyPositive(std::vector &DV, + unsigned Begin, + unsigned End) { + ArrayRef DVRef(DV); + for (unsigned char Direction : DVRef.slice(Begin, End - Begin)) { if (Direction == '<') return true; if (Direction == '>' || Direction == '*') return false; } - return true; + return std::nullopt; } // Checks if it is legal to interchange 2 loops. @@ -256,10 +260,19 @@ static bool isLegalToInterChangeLoops(CharMatrix &DepMatrix, // Create temporary DepVector check its lexicographical order // before and after swapping OuterLoop vs InnerLoop Cur = DepMatrix[Row]; - if (!isLexicographicallyPositive(Cur)) + + // If the direction vector is lexicographically positive due to an element + // to the left of OuterLoopId, it is still positive after exchanging the two + // loops. In such a case we can skip the subsequent check. + if (isLexicographicallyPositive(Cur, 0, OuterLoopId) == true) + continue; + + // Check if the direction vector is lexicographically positive (or zero) + // for both before/after exchanged. + if (isLexicographicallyPositive(Cur, 0, Cur.size()) == false) return false; std::swap(Cur[InnerLoopId], Cur[OuterLoopId]); - if (!isLexicographicallyPositive(Cur)) + if (isLexicographicallyPositive(Cur, 0, Cur.size()) == false) return false; } return true; From cb51f8b0738b122b2279eda36542297cb79ff3b5 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga Date: Mon, 12 May 2025 21:36:06 +0900 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: Michael Kruse --- llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index f6d1860e66e1a..e5178a27f98bf 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -232,13 +232,13 @@ static void interChangeDependencies(CharMatrix &DepMatrix, unsigned FromIndx, } // Check if a direction vector is lexicographically positive. Return true if it -// is positive, nullopt if it is "zero", othrewise false. +// is positive, nullopt if it is "zero", otherwise false. // [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 std::optional isLexicographicallyPositive(std::vector &DV, - unsigned Begin, - unsigned End) { + unsigned Begin = 0, + unsigned End = DV.size()) { ArrayRef DVRef(DV); for (unsigned char Direction : DVRef.slice(Begin, End - Begin)) { if (Direction == '<') @@ -261,9 +261,8 @@ static bool isLegalToInterChangeLoops(CharMatrix &DepMatrix, // before and after swapping OuterLoop vs InnerLoop Cur = DepMatrix[Row]; - // If the direction vector is lexicographically positive due to an element - // to the left of OuterLoopId, it is still positive after exchanging the two - // loops. In such a case we can skip the subsequent check. + // If the surrounding loops already ensure that the direction vector is lexicographically positive, nothing within the loop will be able to break the dependence. + // In such a case we can skip the subsequent check. if (isLexicographicallyPositive(Cur, 0, OuterLoopId) == true) continue; From f226aa175afd56861d4c1e425a1cf4b790cd0118 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga Date: Mon, 12 May 2025 12:41:32 +0000 Subject: [PATCH 3/4] Apply format --- llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index e5178a27f98bf..cca27e07b31b0 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -236,9 +236,9 @@ static void interChangeDependencies(CharMatrix &DepMatrix, unsigned FromIndx, // [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 std::optional isLexicographicallyPositive(std::vector &DV, - unsigned Begin = 0, - unsigned End = DV.size()) { +static std::optional +isLexicographicallyPositive(std::vector &DV, unsigned Begin = 0, + unsigned End = DV.size()) { ArrayRef DVRef(DV); for (unsigned char Direction : DVRef.slice(Begin, End - Begin)) { if (Direction == '<') @@ -261,8 +261,9 @@ static bool isLegalToInterChangeLoops(CharMatrix &DepMatrix, // before and after swapping OuterLoop vs InnerLoop Cur = DepMatrix[Row]; - // If the surrounding loops already ensure that the direction vector is lexicographically positive, nothing within the loop will be able to break the dependence. - // In such a case we can skip the subsequent check. + // If the surrounding loops already ensure that the direction vector is + // lexicographically positive, nothing within the loop will be able to break + // the dependence. In such a case we can skip the subsequent check. if (isLexicographicallyPositive(Cur, 0, OuterLoopId) == true) continue; From 4eaf657d4b71865c67f74c9ba30cea0ab40f78e6 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga Date: Mon, 12 May 2025 12:42:43 +0000 Subject: [PATCH 4/4] Fix default arguments --- llvm/lib/Transforms/Scalar/LoopInterchange.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index cca27e07b31b0..e101943a3f615 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -236,9 +236,9 @@ static void interChangeDependencies(CharMatrix &DepMatrix, unsigned FromIndx, // [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 std::optional -isLexicographicallyPositive(std::vector &DV, unsigned Begin = 0, - unsigned End = DV.size()) { +static std::optional isLexicographicallyPositive(std::vector &DV, + unsigned Begin, + unsigned End) { ArrayRef DVRef(DV); for (unsigned char Direction : DVRef.slice(Begin, End - Begin)) { if (Direction == '<') @@ -249,6 +249,10 @@ isLexicographicallyPositive(std::vector &DV, unsigned Begin = 0, return std::nullopt; } +static std::optional isLexicographicallyPositive(std::vector &DV) { + return isLexicographicallyPositive(DV, 0, DV.size()); +} + // Checks if it is legal to interchange 2 loops. static bool isLegalToInterChangeLoops(CharMatrix &DepMatrix, unsigned InnerLoopId, @@ -269,10 +273,10 @@ static bool isLegalToInterChangeLoops(CharMatrix &DepMatrix, // Check if the direction vector is lexicographically positive (or zero) // for both before/after exchanged. - if (isLexicographicallyPositive(Cur, 0, Cur.size()) == false) + if (isLexicographicallyPositive(Cur) == false) return false; std::swap(Cur[InnerLoopId], Cur[OuterLoopId]); - if (isLexicographicallyPositive(Cur, 0, Cur.size()) == false) + if (isLexicographicallyPositive(Cur) == false) return false; } return true;