diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index 08446ccaa9fca..28ae4f0a0aad9 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -260,6 +260,17 @@ static bool populateDependencyMatrix(CharMatrix &DepMatrix, unsigned Level, Dep.push_back('I'); } + // If all the elements of any direction vector have only '*', legality + // can't be proven. Exit early to save compile time. + if (all_of(Dep, [](char C) { return C == '*'; })) { + ORE->emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "Dependence", + L->getStartLoc(), L->getHeader()) + << "All loops have dependencies in all directions."; + }); + return false; + } + // Test whether the dependency is forward or not. bool IsKnownForward = true; if (Src->getParent() != Dst->getParent()) { diff --git a/llvm/test/Transforms/LoopInterchange/bail-out-all-deps.ll b/llvm/test/Transforms/LoopInterchange/bail-out-all-deps.ll new file mode 100644 index 0000000000000..83cfd91c4da4c --- /dev/null +++ b/llvm/test/Transforms/LoopInterchange/bail-out-all-deps.ll @@ -0,0 +1,44 @@ +; RUN: opt < %s -passes=loop-interchange -pass-remarks-output=%t \ +; RUN: -disable-output +; RUN: FileCheck -input-file %t %s + +; Check that loop interchange bails out early when finding a direction vector +; with all '*' elements. +; +; for (int i = 0; i < 4; i++) +; for (int j = 0; j < 4; j++) +; A[i & val][j & val] = 0; + +; CHECK: --- !Missed +; CHECK-NEXT: Pass: loop-interchange +; CHECK-NEXT: Name: Dependence +; CHECK-NEXT: Function: f +; CHECK-NEXT: Args: +; CHECK-NEXT: - String: All loops have dependencies in all directions. +; CHECK-NEXT: ... +define void @f(ptr %A, i64 %val) { +entry: + br label %for.i.header + +for.i.header: + %i = phi i64 [ 0, %entry ], [ %i.next, %for.i.latch ] + br label %for.j + +for.j: + %j = phi i64 [ 0, %for.i.header ], [ %j.next, %for.j ] + %subscript.0 = and i64 %i, %val + %subscript.1 = and i64 %j, %val + %idx = getelementptr inbounds [4 x i8], ptr %A, i64 %subscript.0, i64 %subscript.1 + store i8 0, ptr %idx + %j.next = add nuw nsw i64 %j, 1 + %exit.j = icmp eq i64 %j.next, 4 + br i1 %exit.j, label %for.i.latch, label %for.j + +for.i.latch: + %i.next = add nuw nsw i64 %i, 1 + %exit.i = icmp eq i64 %i.next, 4 + br i1 %exit.i, label %exit, label %for.i.header + +exit: + ret void +} diff --git a/llvm/test/Transforms/LoopInterchange/confused-dependence.ll b/llvm/test/Transforms/LoopInterchange/confused-dependence.ll index 49b7b0e4797b8..94080949f0af8 100644 --- a/llvm/test/Transforms/LoopInterchange/confused-dependence.ll +++ b/llvm/test/Transforms/LoopInterchange/confused-dependence.ll @@ -1,6 +1,6 @@ -; REQUIRES: asserts -; RUN: opt < %s -passes=loop-interchange -verify-dom-info -verify-loop-info \ -; RUN: -disable-output -debug 2>&1 | FileCheck %s +; RUN: opt < %s -passes=loop-interchange -pass-remarks-output=%t \ +; RUN: -disable-output +; RUN: FileCheck -input-file %t %s ;; In the following case, p0 and p1 may alias, so the direction vector must be [* *]. ;; @@ -10,9 +10,13 @@ ;; p0[4 * i + j] = p1[4 * j + i]; ;; } -; CHECK: Dependency matrix before interchange: -; CHECK-NEXT: * * -; CHECK-NEXT: Processing InnerLoopId = 1 and OuterLoopId = 0 +; CHECK: --- !Missed +; CHECK-NEXT: Pass: loop-interchange +; CHECK-NEXT: Name: Dependence +; CHECK-NEXT: Function: may_alias +; CHECK-NEXT: Args: +; CHECK-NEXT: - String: All loops have dependencies in all directions. +; CHECK-NEXT: ... define void @may_alias(ptr %p0, ptr %p1) { entry: br label %for.i.header diff --git a/llvm/test/Transforms/LoopInterchange/legality-for-scalar-deps.ll b/llvm/test/Transforms/LoopInterchange/legality-for-scalar-deps.ll index c30f9a399fed8..5f4a8486d9ad7 100644 --- a/llvm/test/Transforms/LoopInterchange/legality-for-scalar-deps.ll +++ b/llvm/test/Transforms/LoopInterchange/legality-for-scalar-deps.ll @@ -21,13 +21,13 @@ ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: issue46867 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. ; CHECK: --- !Missed ; CHECK-NEXT: Pass: loop-interchange ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: issue46867 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. define void @issue46867(ptr noundef captures(none) %s, i32 noundef %c, ptr noundef readonly captures(none) %ff) { entry: %tobool7.not = icmp eq i32 %c, 0 @@ -121,7 +121,7 @@ land.end: ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: issue47401 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. define void @issue47401(ptr noundef writeonly captures(none) %e, ptr noundef readonly captures(none) %bb) { entry: br label %for.cond1.preheader @@ -175,7 +175,7 @@ land.end: ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: issue47295 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. define void @issue47295(ptr noundef captures(none) %f, ptr noundef writeonly captures(none) %cc) { entry: br label %for.cond1.preheader @@ -221,7 +221,7 @@ for.body4: ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: issue54176 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. define void @issue54176(i32 noundef %n, i32 noundef %m, ptr noundef captures(none) %aa, ptr noundef readonly captures(none) %bb, ptr noundef writeonly captures(none) %cc) { entry: diff --git a/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll b/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll index 73a566a310157..14836ba73433d 100644 --- a/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll +++ b/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll @@ -71,7 +71,7 @@ for.end19: ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: test01 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. ; CHECK-NEXT: ... ; DELIN: --- !Analysis @@ -147,7 +147,7 @@ define void @test02(i32 %k, i32 %N) { ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: test02 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. ; CHECK-NEXT: ... ; DELIN: --- !Analysis @@ -290,7 +290,7 @@ for.end17: ; CHECK-NEXT: Name: Dependence ; CHECK-NEXT: Function: test04 ; CHECK-NEXT: Args: -; CHECK-NEXT: - String: Cannot interchange loops due to dependences. +; CHECK-NEXT: - String: All loops have dependencies in all directions. ; CHECK-NEXT: ... ; DELIN: --- !Missed diff --git a/llvm/test/Transforms/LoopInterchange/unique-dep-matrix.ll b/llvm/test/Transforms/LoopInterchange/unique-dep-matrix.ll index 68089b43121c5..3af9e7304e3be 100644 --- a/llvm/test/Transforms/LoopInterchange/unique-dep-matrix.ll +++ b/llvm/test/Transforms/LoopInterchange/unique-dep-matrix.ll @@ -2,14 +2,13 @@ ; RUN: opt < %s -passes=loop-interchange -S -debug 2>&1 | FileCheck %s ; CHECK: Dependency matrix before interchange: -; CHECK-NEXT: * * ; CHECK-NEXT: = * ; CHECK-NEXT: < * ; CHECK-NEXT: Processing InnerLoopId ; This example is taken from github issue #54176 ; -define void @foo(i32 noundef %n, i32 noundef %m, ptr nocapture noundef %aa, ptr nocapture noundef readonly %bb, ptr nocapture noundef writeonly %cc) { +define void @foo(i32 noundef %n, i32 noundef %m, ptr nocapture noundef noalias %aa, ptr nocapture noundef readonly noalias %bb, ptr nocapture noundef writeonly noalias %cc) { entry: %arrayidx7 = getelementptr inbounds i8, ptr %aa, i64 512 br label %for.cond1.preheader