Skip to content

[LoopInterchange] Skip legality check if surrounding loops already guarantee dependency (NFC) #139254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 13, 2025

Conversation

kasuga-fj
Copy link
Contributor

@kasuga-fj kasuga-fj commented May 9, 2025

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 a code to skip legality check if surrounding loops already guarantee that the direction vector is lexicographically positive. Note that this is only a small improvement on its own, but it's necessary to relax the legality check I'm working on.

Split off from #118267

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.
@llvmbot
Copy link
Member

llvmbot commented May 9, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Ryotaro Kasuga (kasuga-fj)

Changes

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 &lt; before the loops we are trying to interchange), then obviously it is also positive after exchanging them. For example, for a direction vector [&lt; &lt; &gt;], swapping the last two elements doesn't make it lexicographically negative because the first element is &lt;.
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.

Split off from #118267


Full diff: https://github.com/llvm/llvm-project/pull/139254.diff

1 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/LoopInterchange.cpp (+19-6)
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<char> &DV) {
-  for (unsigned char Direction : DV) {
+static std::optional<bool> isLexicographicallyPositive(std::vector<char> &DV,
+                                                       unsigned Begin,
+                                                       unsigned End) {
+  ArrayRef<char> 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;

Copy link
Member

@Meinersbur Meinersbur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make the title more concrete than "certain cases"? It's not an early exit either

Suggestion: Skip legality check if surronding loops already guarantee dependency

Copy link

github-actions bot commented May 12, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@kasuga-fj kasuga-fj changed the title [LoopInterchange] Exit early in certain cases in legality check (NFC) [LoopInterchange] Skip legality check if surronding loops already guarantee dependency (NFC) May 12, 2025
@kasuga-fj kasuga-fj changed the title [LoopInterchange] Skip legality check if surronding loops already guarantee dependency (NFC) [LoopInterchange] Skip legality check if surrounding loops already guarantee dependency (NFC) May 12, 2025
@kasuga-fj
Copy link
Contributor Author

Can you make the title more concrete than "certain cases"? It's not an early exit either

Suggestion: Skip legality check if surronding loops already guarantee dependency

Fixed, thanks!

@kasuga-fj kasuga-fj merged commit 6dc6ca3 into main May 13, 2025
9 of 11 checks passed
@kasuga-fj kasuga-fj deleted the users/kasuga-fj/loop-interchange-legality-prefix branch May 13, 2025 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants