diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp index ca125d2c0c490..d88fdf41db7a8 100644 --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -276,6 +276,27 @@ static bool hasSupportedLoopDepth(SmallVectorImpl &LoopList, } return true; } + +static bool isComputableLoopNest(ScalarEvolution *SE, + ArrayRef LoopList) { + for (Loop *L : LoopList) { + const SCEV *ExitCountOuter = SE->getBackedgeTakenCount(L); + if (isa(ExitCountOuter)) { + LLVM_DEBUG(dbgs() << "Couldn't compute backedge count\n"); + return false; + } + if (L->getNumBackEdges() != 1) { + LLVM_DEBUG(dbgs() << "NumBackEdges is not equal to 1\n"); + return false; + } + if (!L->getExitingBlock()) { + LLVM_DEBUG(dbgs() << "Loop doesn't have unique exit block\n"); + return false; + } + } + return true; +} + namespace { /// LoopInterchangeLegality checks if it is legal to interchange the loop. @@ -431,25 +452,6 @@ struct LoopInterchange { return processLoopList(LoopList); } - bool isComputableLoopNest(ArrayRef LoopList) { - for (Loop *L : LoopList) { - const SCEV *ExitCountOuter = SE->getBackedgeTakenCount(L); - if (isa(ExitCountOuter)) { - LLVM_DEBUG(dbgs() << "Couldn't compute backedge count\n"); - return false; - } - if (L->getNumBackEdges() != 1) { - LLVM_DEBUG(dbgs() << "NumBackEdges is not equal to 1\n"); - return false; - } - if (!L->getExitingBlock()) { - LLVM_DEBUG(dbgs() << "Loop doesn't have unique exit block\n"); - return false; - } - } - return true; - } - unsigned selectLoopForInterchange(ArrayRef LoopList) { // TODO: Add a better heuristic to select the loop to be interchanged based // on the dependence matrix. Currently we select the innermost loop. @@ -464,10 +466,6 @@ struct LoopInterchange { "Unsupported depth of loop nest."); unsigned LoopNestDepth = LoopList.size(); - if (!isComputableLoopNest(LoopList)) { - LLVM_DEBUG(dbgs() << "Not valid loop candidate for interchange\n"); - return false; - } LLVM_DEBUG(dbgs() << "Processing LoopList of size = " << LoopNestDepth << "\n"); @@ -1761,10 +1759,23 @@ PreservedAnalyses LoopInterchangePass::run(LoopNest &LN, // Ensure minimum depth of the loop nest to do the interchange. if (!hasSupportedLoopDepth(LoopList, ORE)) return PreservedAnalyses::all(); + // Ensure computable loop nest. + if (!isComputableLoopNest(&AR.SE, LoopList)) { + LLVM_DEBUG(dbgs() << "Not valid loop candidate for interchange\n"); + return PreservedAnalyses::all(); + } + + ORE.emit([&]() { + return OptimizationRemarkAnalysis(DEBUG_TYPE, "Dependence", + LN.getOutermostLoop().getStartLoc(), + LN.getOutermostLoop().getHeader()) + << "Computed dependence info, invoking the transform."; + }); + DependenceInfo DI(&F, &AR.AA, &AR.SE, &AR.LI); std::unique_ptr CC = CacheCost::getCacheCost(LN.getOutermostLoop(), AR, DI); - + if (!LoopInterchange(&AR.SE, &AR.LI, &DI, &AR.DT, CC, &ORE).run(LN)) return PreservedAnalyses::all(); U.markLoopNestChanged(true); diff --git a/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll b/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll index 3c7828a49477c..73a566a310157 100644 --- a/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll +++ b/llvm/test/Transforms/LoopInterchange/loop-interchange-optimization-remarks.ll @@ -58,6 +58,14 @@ for.end19: ret void } +; CHECK: --- !Analysis +; CHECK-NEXT: Pass: loop-interchange +; CHECK-NEXT: Name: Dependence +; CHECK-NEXT: Function: test01 +; CHECK-NEXT: Args: +; CHECK-NEXT: - String: Computed dependence info, invoking the transform. +; CHECK-NEXT: ... + ; CHECK: --- !Missed ; CHECK-NEXT: Pass: loop-interchange ; CHECK-NEXT: Name: Dependence @@ -66,6 +74,14 @@ for.end19: ; CHECK-NEXT: - String: Cannot interchange loops due to dependences. ; CHECK-NEXT: ... +; DELIN: --- !Analysis +; DELIN-NEXT: Pass: loop-interchange +; DELIN-NEXT: Name: Dependence +; DELIN-NEXT: Function: test01 +; DELIN-NEXT: Args: +; DELIN-NEXT: - String: Computed dependence info, invoking the transform. +; DELIN-NEXT: ... + ; DELIN: --- !Missed ; DELIN-NEXT: Pass: loop-interchange ; DELIN-NEXT: Name: InterchangeNotProfitable @@ -118,6 +134,14 @@ define void @test02(i32 %k, i32 %N) { ret void } +; CHECK: --- !Analysis +; CHECK-NEXT: Pass: loop-interchange +; CHECK-NEXT: Name: Dependence +; CHECK-NEXT: Function: test02 +; CHECK-NEXT: Args: +; CHECK-NEXT: - String: Computed dependence info, invoking the transform. +; CHECK-NEXT: ... + ; CHECK: --- !Missed ; CHECK-NEXT: Pass: loop-interchange ; CHECK-NEXT: Name: Dependence @@ -126,6 +150,14 @@ define void @test02(i32 %k, i32 %N) { ; CHECK-NEXT: - String: Cannot interchange loops due to dependences. ; CHECK-NEXT: ... +; DELIN: --- !Analysis +; DELIN-NEXT: Pass: loop-interchange +; DELIN-NEXT: Name: Dependence +; DELIN-NEXT: Function: test02 +; DELIN-NEXT: Args: +; DELIN-NEXT: - String: Computed dependence info, invoking the transform. +; DELIN-NEXT: ... + ; DELIN: --- !Passed ; DELIN-NEXT: Pass: loop-interchange ; DELIN-NEXT: Name: Interchanged @@ -174,6 +206,14 @@ for.body4: ; preds = %for.body4, %for.con br i1 %exitcond, label %for.body4, label %for.cond.loopexit } +; CHECK: --- !Analysis +; CHECK-NEXT: Pass: loop-interchange +; CHECK-NEXT: Name: Dependence +; CHECK-NEXT: Function: test03 +; CHECK-NEXT: Args: +; CHECK-NEXT: - String: Computed dependence info, invoking the transform. +; CHECK-NEXT: ... + ; CHECK: --- !Passed ; CHECK-NEXT: Pass: loop-interchange ; CHECK-NEXT: Name: Interchanged @@ -182,6 +222,14 @@ for.body4: ; preds = %for.body4, %for.con ; CHECK-NEXT: - String: Loop interchanged with enclosing loop. ; CHECK-NEXT: ... +; DELIN: --- !Analysis +; DELIN-NEXT: Pass: loop-interchange +; DELIN-NEXT: Name: Dependence +; DELIN-NEXT: Function: test03 +; DELIN-NEXT: Args: +; DELIN-NEXT: - String: Computed dependence info, invoking the transform. +; DELIN-NEXT: ... + ; DELIN: --- !Passed ; DELIN-NEXT: Pass: loop-interchange ; DELIN-NEXT: Name: Interchanged diff --git a/llvm/test/Transforms/LoopInterchange/no-dependence-info.ll b/llvm/test/Transforms/LoopInterchange/no-dependence-info.ll new file mode 100644 index 0000000000000..d37fb46fc5d68 --- /dev/null +++ b/llvm/test/Transforms/LoopInterchange/no-dependence-info.ll @@ -0,0 +1,52 @@ +; RUN: opt %s -passes='loop-interchange' -pass-remarks=loop-interchange -disable-output 2>&1 | FileCheck --allow-empty %s + +target triple = "aarch64-unknown-linux-gnu" + +; CHECK-NOT: Computed dependence info, invoking the transform. + +; For the below test, backedge count cannot be computed. +; Computing backedge count requires only SCEV and should +; not require dependence info. +; +; void bar(int m, int n) { +; for (unsigned int i = 0; i < m; ++i) { +; for (unsigned int j = 0; j < m; ++j) { +; // dummy code +; } +; } +;} + +define void @bar(i32 %m, i32 %n) +{ +entry: + br label %outer.header + +outer.header: + %m_temp1 = phi i32 [%m, %entry], [%m_temp, %outer.latch] + br label %inner.header + + +inner.header: + %n_temp1 = phi i32 [%n, %outer.header], [%n_temp, %inner.latch] + + br label %body + +body: + ; dummy code + +br label %inner.latch + +inner.latch: +%n_temp = add i32 %n_temp1, 1 +%cmp2 = icmp eq i32 %n_temp, 1 +br i1 %cmp2, label %outer.latch, label %inner.header + +outer.latch: +%m_temp = add i32 %n, 1 +%cmp3 = icmp eq i32 %m_temp, 1 +br i1 %cmp3, label %exit, label %outer.header + +exit: +ret void +} + diff --git a/llvm/test/Transforms/LoopInterchange/pr43326-ideal-access-pattern.ll b/llvm/test/Transforms/LoopInterchange/pr43326-ideal-access-pattern.ll index def68ca3cd07e..520e1ee3506da 100644 --- a/llvm/test/Transforms/LoopInterchange/pr43326-ideal-access-pattern.ll +++ b/llvm/test/Transforms/LoopInterchange/pr43326-ideal-access-pattern.ll @@ -14,6 +14,14 @@ ; } ; } +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: pr43326-triply-nested +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Passed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Interchanged diff --git a/llvm/test/Transforms/LoopInterchange/pr43326.ll b/llvm/test/Transforms/LoopInterchange/pr43326.ll index 4dbb06780a898..c25c4fadd3042 100644 --- a/llvm/test/Transforms/LoopInterchange/pr43326.ll +++ b/llvm/test/Transforms/LoopInterchange/pr43326.ll @@ -8,6 +8,14 @@ @d = global i32 0 @e = global [1 x [1 x i32]] zeroinitializer +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: pr43326 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Passed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Interchanged diff --git a/llvm/test/Transforms/LoopInterchange/pr48212.ll b/llvm/test/Transforms/LoopInterchange/pr48212.ll index b580794ab7d36..936c53e217540 100644 --- a/llvm/test/Transforms/LoopInterchange/pr48212.ll +++ b/llvm/test/Transforms/LoopInterchange/pr48212.ll @@ -2,6 +2,14 @@ ; RUN: -verify-dom-info -verify-loop-info -verify-loop-lcssa 2>&1 ; RUN: FileCheck --input-file=%t --check-prefix=REMARKS %s +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: pr48212 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Passed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Interchanged diff --git a/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll b/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll index eea0c2635d595..27d99e05e84ee 100644 --- a/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll +++ b/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll @@ -5,6 +5,14 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test1 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Passed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Interchanged @@ -77,6 +85,14 @@ for1.loopexit: ; preds = %for1.inc ; In this test case, the inner reduction PHI %inner does not involve the outer ; reduction PHI %sum.outer, do not interchange. +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test2 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Missed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: UnsupportedPHIOuter @@ -114,6 +130,14 @@ for1.loopexit: ; preds = %for1.inc ; Check that we do not interchange if there is an additional instruction ; between the outer and inner reduction PHIs. +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test3 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Missed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: UnsupportedPHIOuter @@ -151,6 +175,14 @@ for1.loopexit: ; preds = %for1.inc } ; Check that we do not interchange if reduction is stored in an invariant address inside inner loop +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test4 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Missed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Dependence @@ -190,6 +222,14 @@ for1.loopexit: ; preds = %for1.inc ; Check that we do not interchange or crash if the PHI in the outer loop gets a ; constant from the inner loop. +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test_constant_inner_loop_res +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Missed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: UnsupportedPHIOuter @@ -229,6 +269,14 @@ for1.loopexit: ; preds = %for1.inc ; Floating point reductions are interchanged if all the fp instructions ; involved allow reassociation. +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test5 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Passed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: Interchanged @@ -269,6 +317,14 @@ for.exit: ; preds = %outer.inc ; Floating point reductions are not interchanged if not all the fp instructions ; involved allow reassociation. +; REMARKS: --- !Analysis +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: Dependence +; REMARKS-NEXT: Function: test6 +; REMARKS-NEXT: Args: +; REMARKS-NEXT: - String: Computed dependence info, invoking the transform. +; REMARKS-NEXT: ... + ; REMARKS: --- !Missed ; REMARKS-NEXT: Pass: loop-interchange ; REMARKS-NEXT: Name: UnsupportedPHIOuter