[polly] [Polly][CodePreparation] Extract common code of LPM and NPM (PR #140419)

Michael Kruse via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 31 08:38:57 PDT 2025


https://github.com/Meinersbur updated https://github.com/llvm/llvm-project/pull/140419

>From 3bcaf3f2809410d7f1c87cf9d72753ba94ba63ac Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Fri, 24 Jan 2025 17:58:50 +0100
Subject: [PATCH 1/4] Remove PolyhedralInfo

---
 polly/include/polly/LinkAllPasses.h           |   6 -
 polly/include/polly/PolyhedralInfo.h          | 104 ---------
 polly/lib/Analysis/PolyhedralInfo.cpp         | 215 ------------------
 polly/lib/CMakeLists.txt                      |   1 -
 polly/lib/Support/RegisterPasses.cpp          |   3 -
 .../OpenMP/multiple_loops_outer_parallel.ll   |   3 -
 .../OpenMP/nested_loop_both_parallel.ll       |   4 -
 .../nested_loop_both_parallel_parametric.ll   |   4 -
 .../OpenMP/nested_loop_inner_parallel.ll      |   4 -
 .../OpenMP/nested_loop_outer_parallel.ll      |   4 -
 .../OpenMP/single_loop_param_non_parallel.ll  |   2 -
 .../OpenMP/single_loop_param_parallel.ll      |   2 -
 .../single_loop_param_parallel_computeout.ll  |   2 -
 .../dependence_distance_constant.ll           |   3 -
 .../dependence_distance_multiple_constant.ll  |   2 -
 .../dependence_distance_parametric.ll         |   3 -
 .../dependence_distance_parametric_expr.ll    |   3 -
 .../IstAstInfo/dependence_distance_varying.ll |   2 -
 ...pendence_distance_varying_in_outer_loop.ll |   3 -
 .../dependence_distance_varying_multiple.ll   |   2 -
 ...duction_clauses_multidimensional_access.ll |   4 -
 .../IstAstInfo/reduction_in_one_dimension.ll  |   3 -
 .../IstAstInfo/reduction_loop_reversal.ll     |   4 -
 .../IstAstInfo/reduction_modulo_schedule.ll   |   4 -
 24 files changed, 387 deletions(-)
 delete mode 100644 polly/include/polly/PolyhedralInfo.h
 delete mode 100644 polly/lib/Analysis/PolyhedralInfo.cpp

diff --git a/polly/include/polly/LinkAllPasses.h b/polly/include/polly/LinkAllPasses.h
index a2f8f33299918..54e7c5a43ab93 100644
--- a/polly/include/polly/LinkAllPasses.h
+++ b/polly/include/polly/LinkAllPasses.h
@@ -42,8 +42,6 @@ llvm::Pass *createJSONExporterPass();
 llvm::Pass *createJSONImporterPass();
 llvm::Pass *createJSONImporterPrinterLegacyPass(llvm::raw_ostream &OS);
 llvm::Pass *createPollyCanonicalizePass();
-llvm::Pass *createPolyhedralInfoPass();
-llvm::Pass *createPolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS);
 llvm::Pass *createScopDetectionWrapperPassPass();
 llvm::Pass *createScopDetectionPrinterLegacyPass(llvm::raw_ostream &OS);
 llvm::Pass *createScopInfoRegionPassPass();
@@ -99,8 +97,6 @@ struct PollyForcePassLinking {
     polly::createScopInfoWrapperPassPass();
     polly::createScopInfoPrinterLegacyFunctionPass(llvm::outs());
     polly::createPollyCanonicalizePass();
-    polly::createPolyhedralInfoPass();
-    polly::createPolyhedralInfoPrinterLegacyPass(llvm::outs());
     polly::createIslAstInfoWrapperPassPass();
     polly::createIslAstInfoPrinterLegacyPass(llvm::outs());
     polly::createCodeGenerationPass();
@@ -156,8 +152,6 @@ void initializeDeLICMPrinterLegacyPassPass(llvm::PassRegistry &);
 void initializeSimplifyWrapperPassPass(llvm::PassRegistry &);
 void initializeSimplifyPrinterLegacyPassPass(llvm::PassRegistry &);
 void initializePruneUnprofitableWrapperPassPass(llvm::PassRegistry &);
-void initializePolyhedralInfoPass(llvm::PassRegistry &);
-void initializePolyhedralInfoPrinterLegacyPassPass(llvm::PassRegistry &);
 } // namespace llvm
 
 #endif
diff --git a/polly/include/polly/PolyhedralInfo.h b/polly/include/polly/PolyhedralInfo.h
deleted file mode 100644
index b7534cd6b8df7..0000000000000
--- a/polly/include/polly/PolyhedralInfo.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//===- polly/PolyhedralInfo.h - PolyhedralInfo class definition -*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// This file contains the declaration of the PolyhedralInfo class, which will
-/// provide an interface to expose polyhedral analysis information of Polly.
-///
-/// This is work in progress. We will add more API's as and when deemed
-/// required.
-//===----------------------------------------------------------------------===///
-
-#ifndef POLLY_POLYHEDRAL_INFO_H
-#define POLLY_POLYHEDRAL_INFO_H
-
-#include "llvm/Pass.h"
-#include "isl/aff_type.h"
-#include "isl/ctx.h"
-#include "isl/union_map_type.h"
-
-namespace llvm {
-class Loop;
-} // namespace llvm
-
-namespace polly {
-
-class Scop;
-class ScopInfo;
-class DependenceInfoWrapperPass;
-
-class PolyhedralInfo final : public llvm::FunctionPass {
-public:
-  static char ID; // Pass identification, replacement for typeid
-
-  /// Construct a new PolyhedralInfo pass.
-  PolyhedralInfo() : FunctionPass(ID) {}
-  ~PolyhedralInfo() {}
-
-  /// Check if a given loop is parallel.
-  ///
-  /// @param L The loop.
-  ///
-  /// @return  Returns true, if loop is parallel false otherwise.
-  bool isParallel(llvm::Loop *L) const;
-
-  /// Return the SCoP containing the @p L loop.
-  ///
-  /// @param L The loop.
-  ///
-  /// @return  Returns the SCoP containing the given loop.
-  ///          Returns null if the loop is not contained in any SCoP.
-  const Scop *getScopContainingLoop(llvm::Loop *L) const;
-
-  /// Computes the partial schedule for the given @p L loop.
-  ///
-  /// @param S The SCoP containing the given loop
-  /// @param L The loop.
-  ///
-  /// @return  Returns the partial schedule for the given loop
-  __isl_give isl_union_map *getScheduleForLoop(const Scop *S,
-                                               llvm::Loop *L) const;
-
-  /// Get the SCoP and dependence analysis information for @p F.
-  bool runOnFunction(llvm::Function &F) override;
-
-  /// Release the internal memory.
-  void releaseMemory() override {}
-
-  /// Print to @p OS if each dimension of a loop nest is parallel or not.
-  void print(llvm::raw_ostream &OS,
-             const llvm::Module *M = nullptr) const override;
-
-  /// Register all analyses and transformation required.
-  void getAnalysisUsage(llvm::AnalysisUsage &AU) const override;
-
-private:
-  /// Check if a given loop is parallel or vectorizable.
-  ///
-  /// @param L             The loop.
-  /// @param MinDepDistPtr If not nullptr, the minimal dependence distance will
-  ///                      be returned at the address of that pointer
-  ///
-  /// @return  Returns true if loop is parallel or vectorizable, false
-  ///          otherwise.
-  bool checkParallel(llvm::Loop *L,
-                     __isl_give isl_pw_aff **MinDepDistPtr = nullptr) const;
-
-  ScopInfo *SI;
-  DependenceInfoWrapperPass *DI;
-};
-
-llvm::Pass *createPolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS);
-} // end namespace polly
-
-namespace llvm {
-class PassRegistry;
-void initializePolyhedralInfoPass(llvm::PassRegistry &);
-void initializePolyhedralInfoPrinterLegacyPassPass(llvm::PassRegistry &);
-} // namespace llvm
-
-#endif
diff --git a/polly/lib/Analysis/PolyhedralInfo.cpp b/polly/lib/Analysis/PolyhedralInfo.cpp
deleted file mode 100644
index 8d8e81a9049df..0000000000000
--- a/polly/lib/Analysis/PolyhedralInfo.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-//===--------- PolyhedralInfo.cpp  - Create Scops from LLVM IR-------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// An interface to the Polyhedral analysis engine(Polly) of LLVM.
-//
-// This pass provides an interface to the polyhedral analysis performed by
-// Polly.
-//
-// This interface provides basic interface like isParallel, isVectorizable
-// that can be used in LLVM transformation passes.
-//
-// Work in progress, this file is subject to change.
-//
-//===----------------------------------------------------------------------===//
-
-#include "polly/PolyhedralInfo.h"
-#include "polly/DependenceInfo.h"
-#include "polly/LinkAllPasses.h"
-#include "polly/Options.h"
-#include "polly/ScopInfo.h"
-#include "polly/Support/GICHelper.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/InitializePasses.h"
-#include "llvm/Support/Debug.h"
-#include "isl/union_map.h"
-
-using namespace llvm;
-using namespace polly;
-
-#include "polly/Support/PollyDebug.h"
-#define DEBUG_TYPE "polyhedral-info"
-
-static cl::opt<bool> CheckParallel("polly-check-parallel",
-                                   cl::desc("Check for parallel loops"),
-                                   cl::Hidden, cl::cat(PollyCategory));
-
-static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
-                                       cl::desc("Check for vectorizable loops"),
-                                       cl::Hidden, cl::cat(PollyCategory));
-
-void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
-  AU.addRequiredTransitive<DependenceInfoWrapperPass>();
-  AU.addRequired<LoopInfoWrapperPass>();
-  AU.addRequiredTransitive<ScopInfoWrapperPass>();
-  AU.setPreservesAll();
-}
-
-bool PolyhedralInfo::runOnFunction(Function &F) {
-  DI = &getAnalysis<DependenceInfoWrapperPass>();
-  SI = getAnalysis<ScopInfoWrapperPass>().getSI();
-  return false;
-}
-
-void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
-  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
-  for (auto *TopLevelLoop : LI) {
-    for (auto *L : depth_first(TopLevelLoop)) {
-      OS.indent(2) << L->getHeader()->getName() << ":\t";
-      if (CheckParallel && isParallel(L))
-        OS << "Loop is parallel.\n";
-      else if (CheckParallel)
-        OS << "Loop is not parallel.\n";
-    }
-  }
-}
-
-bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
-  bool IsParallel;
-  const Scop *S = getScopContainingLoop(L);
-  if (!S)
-    return false;
-  const Dependences &D =
-      DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
-  if (!D.hasValidDependences())
-    return false;
-  POLLY_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
-
-  isl_union_map *Deps =
-      D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
-                       Dependences::TYPE_WAR | Dependences::TYPE_RED)
-          .release();
-
-  POLLY_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null")
-                     << "\n");
-
-  isl_union_map *Schedule = getScheduleForLoop(S, L);
-  POLLY_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null")
-                     << "\n");
-
-  IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
-  isl_union_map_free(Schedule);
-  return IsParallel;
-}
-
-bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
-
-const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
-  assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
-  for (auto &It : *SI) {
-    Region *R = It.first;
-    if (R->contains(L))
-      return It.second.get();
-  }
-  return nullptr;
-}
-
-//  Given a Loop and the containing SCoP, we compute the partial schedule
-//  by taking union of individual schedules of each ScopStmt within the loop
-//  and projecting out the inner dimensions from the range of the schedule.
-//   for (i = 0; i < n; i++)
-//      for (j = 0; j < n; j++)
-//        A[j] = 1;  //Stmt
-//
-//  The original schedule will be
-//    Stmt[i0, i1] -> [i0, i1]
-//  The schedule for the outer loop will be
-//    Stmt[i0, i1] -> [i0]
-//  The schedule for the inner loop will be
-//    Stmt[i0, i1] -> [i0, i1]
-__isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
-                                                             Loop *L) const {
-  isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
-  int CurrDim = S->getRelativeLoopDepth(L);
-  POLLY_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
-  assert(CurrDim >= 0 && "Loop in region should have at least depth one");
-
-  for (auto &SS : *S) {
-    if (L->contains(SS.getSurroundingLoop())) {
-
-      unsigned int MaxDim = SS.getNumIterators();
-      POLLY_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
-      isl_map *ScheduleMap = SS.getSchedule().release();
-      assert(
-          ScheduleMap &&
-          "Schedules that contain extension nodes require special handling.");
-
-      ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
-                                        MaxDim - CurrDim - 1);
-      ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
-                                         SS.getDomainId().release());
-      Schedule =
-          isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
-    }
-  }
-  Schedule = isl_union_map_coalesce(Schedule);
-  return Schedule;
-}
-
-char PolyhedralInfo::ID = 0;
-
-Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
-
-INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
-                      "Polly - Interface to polyhedral analysis engine", false,
-                      false);
-INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
-INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
-INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
-INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
-                    "Polly - Interface to polyhedral analysis engine", false,
-                    false)
-
-//===----------------------------------------------------------------------===//
-
-namespace {
-/// Print result from PolyhedralInfo.
-class PolyhedralInfoPrinterLegacyPass final : public FunctionPass {
-public:
-  static char ID;
-
-  PolyhedralInfoPrinterLegacyPass() : PolyhedralInfoPrinterLegacyPass(outs()) {}
-  explicit PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS)
-      : FunctionPass(ID), OS(OS) {}
-
-  bool runOnFunction(Function &F) override {
-    PolyhedralInfo &P = getAnalysis<PolyhedralInfo>();
-
-    OS << "Printing analysis '" << P.getPassName() << "' for function '"
-       << F.getName() << "':\n";
-    P.print(OS);
-
-    return false;
-  }
-
-  void getAnalysisUsage(AnalysisUsage &AU) const override {
-    FunctionPass::getAnalysisUsage(AU);
-    AU.addRequired<PolyhedralInfo>();
-    AU.setPreservesAll();
-  }
-
-private:
-  llvm::raw_ostream &OS;
-};
-
-char PolyhedralInfoPrinterLegacyPass::ID = 0;
-} // namespace
-
-Pass *polly::createPolyhedralInfoPrinterLegacyPass(raw_ostream &OS) {
-  return new PolyhedralInfoPrinterLegacyPass(OS);
-}
-
-INITIALIZE_PASS_BEGIN(
-    PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
-    "Polly - Print interface to polyhedral analysis engine analysis", false,
-    false);
-INITIALIZE_PASS_DEPENDENCY(PolyhedralInfo);
-INITIALIZE_PASS_END(
-    PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
-    "Polly - Print interface to polyhedral analysis engine analysis", false,
-    false)
diff --git a/polly/lib/CMakeLists.txt b/polly/lib/CMakeLists.txt
index d91f4ecd37e6c..0ed673815ff34 100644
--- a/polly/lib/CMakeLists.txt
+++ b/polly/lib/CMakeLists.txt
@@ -43,7 +43,6 @@ add_llvm_pass_plugin(Polly
   NO_MODULE
   SUBPROJECT Polly
   Analysis/DependenceInfo.cpp
-  Analysis/PolyhedralInfo.cpp
   Analysis/ScopDetection.cpp
   Analysis/ScopDetectionDiagnostic.cpp
   Analysis/ScopInfo.cpp
diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp
index 503c3ae1e07c7..a46e61aafbeb7 100644
--- a/polly/lib/Support/RegisterPasses.cpp
+++ b/polly/lib/Support/RegisterPasses.cpp
@@ -30,7 +30,6 @@
 #include "polly/JSONExporter.h"
 #include "polly/LinkAllPasses.h"
 #include "polly/MaximalStaticExpansion.h"
-#include "polly/PolyhedralInfo.h"
 #include "polly/PruneUnprofitable.h"
 #include "polly/ScheduleOptimizer.h"
 #include "polly/ScopDetection.h"
@@ -232,8 +231,6 @@ void initializePollyPasses(llvm::PassRegistry &Registry) {
   initializeIslScheduleOptimizerWrapperPassPass(Registry);
   initializeIslScheduleOptimizerPrinterLegacyPassPass(Registry);
   initializePollyCanonicalizePass(Registry);
-  initializePolyhedralInfoPass(Registry);
-  initializePolyhedralInfoPrinterLegacyPassPass(Registry);
   initializeScopDetectionWrapperPassPass(Registry);
   initializeScopDetectionPrinterLegacyPassPass(Registry);
   initializeScopInlinerPass(Registry);
diff --git a/polly/test/IstAstInfo/OpenMP/multiple_loops_outer_parallel.ll b/polly/test/IstAstInfo/OpenMP/multiple_loops_outer_parallel.ll
index 00f18aebbcd5a..ec1ccdce94508 100644
--- a/polly/test/IstAstInfo/OpenMP/multiple_loops_outer_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/multiple_loops_outer_parallel.ll
@@ -1,13 +1,10 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -polly-parallel-force -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;       void jd(int *A) {
 ; CHECK:  #pragma omp parallel for
-; PINFO:  for.cond2: Loop is parallel.
 ;         for (int i = 0; i < 1024; i++)
 ;           A[i] = 1;
 ; CHECK:  #pragma omp parallel for
-; PINFO:  for.cond: Loop is parallel.
 ;         for (int i = 0; i < 1024; i++)
 ;           A[i] = A[i] * 2;
 ;       }
diff --git a/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel.ll b/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel.ll
index bcb35cb4b07c1..9c00690605408 100644
--- a/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < 1024; i++)
@@ -50,6 +49,3 @@ ret:
 ; CHECK-NOT:   #pragma omp parallel for
 ; CHECK:       for (int c1 = 0; c1 <= 1023; c1 += 1)
 ; CHECK:         Stmt_loop_body(c0, c1);
-;
-; PINFO:      loop.i: Loop is parallel.
-; PINFO-NEXT: loop.j: Loop is parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel_parametric.ll b/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel_parametric.ll
index e2ff5d5756b13..356762a2ae5b9 100644
--- a/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel_parametric.ll
+++ b/polly/test/IstAstInfo/OpenMP/nested_loop_both_parallel_parametric.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -polly-parallel-force -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 ; int A[1024][1024];
 ; void bar(int n) {
@@ -47,6 +46,3 @@ ret:
 ; CHECK:     #pragma simd
 ; CHECK:     for (int c1 = 0; c1 < n; c1 += 1)
 ; CHECK:       Stmt_loop_body(c0, c1);
-
-; PINFO:      loop.i: Loop is parallel.
-; PINFO-NEXT: loop.j: Loop is parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/nested_loop_inner_parallel.ll b/polly/test/IstAstInfo/OpenMP/nested_loop_inner_parallel.ll
index 17ef7fe6f251d..066fc39def6ac 100644
--- a/polly/test/IstAstInfo/OpenMP/nested_loop_inner_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/nested_loop_inner_parallel.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -polly-parallel-force -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output< %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < n; i++)
@@ -45,6 +44,3 @@ ret:
 ; CHECK:   #pragma omp parallel for
 ; CHECK:   for (int c1 = 0; c1 < n; c1 += 1)
 ; CHECK:     Stmt_loop_body(c0, c1);
-
-; PINFO:      loop.i: Loop is not parallel.
-; PINFO-NEXT: loop.j: Loop is parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/nested_loop_outer_parallel.ll b/polly/test/IstAstInfo/OpenMP/nested_loop_outer_parallel.ll
index bc381e2c87fdb..77dd55cb7605e 100644
--- a/polly/test/IstAstInfo/OpenMP/nested_loop_outer_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/nested_loop_outer_parallel.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < n; i++)
@@ -44,6 +43,3 @@ ret:
 ; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
 ; CHECK:   for (int c1 = 0; c1 < n; c1 += 1)
 ; CHECK:     Stmt_loop_body(c0, c1);
-
-; PINFO:      loop.i: Loop is parallel.
-; PINFO-NEXT: loop.j: Loop is not parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/single_loop_param_non_parallel.ll b/polly/test/IstAstInfo/OpenMP/single_loop_param_non_parallel.ll
index ee02dafeedeb1..b61ebc9379b7f 100644
--- a/polly/test/IstAstInfo/OpenMP/single_loop_param_non_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/single_loop_param_non_parallel.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < n; i++)
@@ -31,4 +30,3 @@ ret:
 
 ; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
 ; CHECK:   Stmt_loop_body(c0)
-; PINFO: loop.header: Loop is not parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel.ll b/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel.ll
index a5831302471ee..5c92a91681867 100644
--- a/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel.ll
+++ b/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -polly-parallel-force -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < n; i++)
@@ -34,4 +33,3 @@ ret:
 ; CHECK: #pragma omp parallel for
 ; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
 ; CHECK:   Stmt_loop_body(c0)
-; PINFO: loop.header: Loop is parallel.
diff --git a/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel_computeout.ll b/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel_computeout.ll
index 31a906ed403c8..352d879199675 100644
--- a/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel_computeout.ll
+++ b/polly/test/IstAstInfo/OpenMP/single_loop_param_parallel_computeout.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-parallel -polly-dependences-computeout=1 -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
 
 ; for (i = 0; i < n; i++)
@@ -34,4 +33,3 @@ ret:
 ; CHECK-NOT: #pragma omp parallel for
 ; CHECK: for (int c0 = 0; c0 < n; c0 += 1)
 ; CHECK:   Stmt_loop_body(c0)
-; PINFO: loop.header: Loop is parallel.
diff --git a/polly/test/IstAstInfo/dependence_distance_constant.ll b/polly/test/IstAstInfo/dependence_distance_constant.ll
index 8b0e4d267c14d..9b7fb93f2f676 100644
--- a/polly/test/IstAstInfo/dependence_distance_constant.ll
+++ b/polly/test/IstAstInfo/dependence_distance_constant.ll
@@ -1,12 +1,9 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *A, int N) {
 ; CHECK:   #pragma minimal dependence distance: 1
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int j = 0; j < N; j++)
 ; CHECK:      #pragma minimal dependence distance: 8
-; PINFO-NEXT: for.cond1: Loop is not parallel.
 ;             for (int i = 0; i < N; i++)
 ;               A[i + 8] = A[i] + 1;
 ;        }
diff --git a/polly/test/IstAstInfo/dependence_distance_multiple_constant.ll b/polly/test/IstAstInfo/dependence_distance_multiple_constant.ll
index 4dae80902457c..bc21e9e07ad89 100644
--- a/polly/test/IstAstInfo/dependence_distance_multiple_constant.ll
+++ b/polly/test/IstAstInfo/dependence_distance_multiple_constant.ll
@@ -1,9 +1,7 @@
 ; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-stmt-granularity=bb -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *restrict A, int *restrict B, int N) {
 ; CHECK:   #pragma minimal dependence distance: 5
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int i = 0; i < N; i++) {
 ;            A[i + 7] = A[i] + 1;
 ;            B[i + 5] = B[i] + 1;
diff --git a/polly/test/IstAstInfo/dependence_distance_parametric.ll b/polly/test/IstAstInfo/dependence_distance_parametric.ll
index 3133b732c9dbc..fa569a8386b86 100644
--- a/polly/test/IstAstInfo/dependence_distance_parametric.ll
+++ b/polly/test/IstAstInfo/dependence_distance_parametric.ll
@@ -1,12 +1,9 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *A, int N, int c) {
 ; CHECK:   #pragma minimal dependence distance: 1
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int j = 0; j < N; j++)
 ; CHECK:      #pragma minimal dependence distance: max(-c, c)
-; PINFO-NEXT: for.cond1: Loop is not parallel.
 ;             for (int i = 0; i < N; i++)
 ;               A[i + c] = A[i] + 1;
 ;        }
diff --git a/polly/test/IstAstInfo/dependence_distance_parametric_expr.ll b/polly/test/IstAstInfo/dependence_distance_parametric_expr.ll
index 5cce8c84a903c..7f280e0c542ca 100644
--- a/polly/test/IstAstInfo/dependence_distance_parametric_expr.ll
+++ b/polly/test/IstAstInfo/dependence_distance_parametric_expr.ll
@@ -1,12 +1,9 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *A, int N, int c, int v) {
 ; CHECK:   #pragma minimal dependence distance: 1
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int j = 0; j < N; j++)
 ; CHECK:      #pragma minimal dependence distance: max(-c - v, c + v)
-; PINFO-NEXT: for.cond1: Loop is not parallel.
 ;             for (int i = 0; i < N; i++)
 ;               A[i + c + v] = A[i] + 1;
 ;        }
diff --git a/polly/test/IstAstInfo/dependence_distance_varying.ll b/polly/test/IstAstInfo/dependence_distance_varying.ll
index 71c045b69e28a..d609c2f210f8d 100644
--- a/polly/test/IstAstInfo/dependence_distance_varying.ll
+++ b/polly/test/IstAstInfo/dependence_distance_varying.ll
@@ -1,9 +1,7 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;         void f(int *A, int N) {
 ; CHECK:    #pragma minimal dependence distance: -(N % 2) + 2
-; PINFO:    for.cond: Loop is not parallel.
 ;           for (int i = 0; i < N; i++)
 ;             A[i] = A[N - i] + 1;
 ;         }
diff --git a/polly/test/IstAstInfo/dependence_distance_varying_in_outer_loop.ll b/polly/test/IstAstInfo/dependence_distance_varying_in_outer_loop.ll
index 463e942fc958a..8ed3220353c1b 100644
--- a/polly/test/IstAstInfo/dependence_distance_varying_in_outer_loop.ll
+++ b/polly/test/IstAstInfo/dependence_distance_varying_in_outer_loop.ll
@@ -1,12 +1,9 @@
 ; RUN: opt %loadPolly -polly-canonicalize -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *restrict A, int *restrict sum) {
 ; CHECK:   #pragma minimal dependence distance: 1
-; PINFO:    for.cond: Loop is not parallel.
 ;          for (int j = 0; j < 1024; j++)
 ; CHECK:      #pragma minimal dependence distance: 1
-; PINFO-NEXT: for.cond1: Loop is not parallel.
 ;             for (int i = j; i < 1024; i++)
 ;               A[i - 3] = A[j] * 2 + A[j] + 2;
 ;        }
diff --git a/polly/test/IstAstInfo/dependence_distance_varying_multiple.ll b/polly/test/IstAstInfo/dependence_distance_varying_multiple.ll
index 67917b4a919f7..73768e9c308a4 100644
--- a/polly/test/IstAstInfo/dependence_distance_varying_multiple.ll
+++ b/polly/test/IstAstInfo/dependence_distance_varying_multiple.ll
@@ -1,10 +1,8 @@
 ; RUN: opt %loadPolly -basic-aa -polly-stmt-granularity=bb -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -polly-stmt-granularity=bb -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ;        void f(int *restrict A, int *restrict B, int *restrict C, int *restrict D,
 ;               int *restrict E, int N) {
 ; CHECK:   #pragma minimal dependence distance: N >= 35 ? 1 : N >= 17 && N <= 34 ? 2 : 5
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int i = 0; i < N; i++) {
 ;            A[i] = A[100 - 2 * i] + 1;
 ;            B[i] = B[100 - 3 * i] + 1;
diff --git a/polly/test/IstAstInfo/reduction_clauses_multidimensional_access.ll b/polly/test/IstAstInfo/reduction_clauses_multidimensional_access.ll
index b588e42df5d1e..697b6ca50d444 100644
--- a/polly/test/IstAstInfo/reduction_clauses_multidimensional_access.ll
+++ b/polly/test/IstAstInfo/reduction_clauses_multidimensional_access.ll
@@ -1,14 +1,10 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ; CHECK: #pragma known-parallel reduction (^ : MemRef_sum)
 ;        void f(int N, int M, int P, int sum[P][M]) {
-; PINFO:   for.cond: Loop is not parallel.
 ;          for (int i = 0; i < N; i++)
-; PINFO-NEXT: for.cond1: Loop is parallel.
 ;             for (int j = 0; j < P; j++)
 ; CHECK:        #pragma simd
-; PINFO-NEXT:   for.cond4: Loop is parallel.
 ;               for (int k = 0; k < M; k++)
 ;                 sum[j][k] ^= j;
 ;        }
diff --git a/polly/test/IstAstInfo/reduction_in_one_dimension.ll b/polly/test/IstAstInfo/reduction_in_one_dimension.ll
index 86a1b67f7292d..797115b6f8d70 100644
--- a/polly/test/IstAstInfo/reduction_in_one_dimension.ll
+++ b/polly/test/IstAstInfo/reduction_in_one_dimension.ll
@@ -1,13 +1,10 @@
 ; RUN: opt %loadPolly -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ; Verify that we won't privatize anything in the outer dimension
 ;
 ; CHECK:    #pragma known-parallel
-; PINFO:    for.cond: Loop is parallel.
 ; CHECK:    for (int c0 = 0; c0 < 2 * n; c0 += 1)
 ; CHECK:      #pragma simd reduction
-; PINFO-NEXT: for.cond1: Loop is not parallel.
 ; CHECK:      for (int c1 = 0; c1 <= 1023; c1 += 1)
 ; CHECK:        Stmt_for_body3(c0, c1);
 ;
diff --git a/polly/test/IstAstInfo/reduction_loop_reversal.ll b/polly/test/IstAstInfo/reduction_loop_reversal.ll
index c940f5c08fa1e..d30119787d8e0 100644
--- a/polly/test/IstAstInfo/reduction_loop_reversal.ll
+++ b/polly/test/IstAstInfo/reduction_loop_reversal.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ; CHECK-NOT: #pragma simd{{\s*$}}
 ; CHECK: #pragma simd reduction
@@ -7,9 +6,6 @@
 ; CHECK: #pragma simd{{\s*$}}
 ; CHECK: Stmt_S1(n - c1)
 ;
-; PINFO:       for.cond2: Loop is parallel.
-; PINFO-NEXT:  for.cond: Loop is not parallel.
-;
 ;    void rlr(int *A, long n) {
 ;      for (long i = 0; i < 2 * n; i++)
 ; S0:    A[0] += i;
diff --git a/polly/test/IstAstInfo/reduction_modulo_schedule.ll b/polly/test/IstAstInfo/reduction_modulo_schedule.ll
index 21a78e5487621..c39ffa591484d 100644
--- a/polly/test/IstAstInfo/reduction_modulo_schedule.ll
+++ b/polly/test/IstAstInfo/reduction_modulo_schedule.ll
@@ -1,5 +1,4 @@
 ; RUN: opt %loadPolly -polly-import-jscop -polly-print-ast -polly-ast-detect-parallel -disable-output < %s | FileCheck %s
-; RUN: opt %loadPolly -print-polyhedral-info -polly-check-parallel -disable-output < %s | FileCheck %s -check-prefix=PINFO
 ;
 ; CHECK:          #pragma known-parallel reduction (+ : MemRef_A)
 ; CHECK-NEXT:     for (int c0 = 0; c0 <= 2; c0 += 1) {
@@ -13,9 +12,6 @@
 ; CHECK-NEXT:           Stmt_S0(c1);
 ; CHECK-NEXT:     }
 ;
-; PINFO:      for.cond2: Loop is parallel.
-; PINFO-NEXT: for.cond: Loop is not parallel.
-;
 ;    void rms(int *A, long n) {
 ;      for (long i = 0; i < 2 * n; i++)
 ; S0:    A[0] += i;

>From 06b025db36dff8c1a3b0b22ae884d6506611f455 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Sun, 2 Feb 2025 18:48:32 +0100
Subject: [PATCH 2/4] Update ScopInliner to support NPM

---
 polly/docs/ReleaseNotes.rst                   |   2 +
 polly/include/polly/LinkAllPasses.h           |   2 +-
 polly/include/polly/ScopInliner.h             |  34 ++++
 polly/lib/Support/PollyPasses.def             |   6 +
 polly/lib/Support/RegisterPasses.cpp          |  41 ++++-
 polly/lib/Transform/ScopInliner.cpp           | 159 +++++++++++-------
 polly/test/ScopInliner/ignore-declares.ll     |   3 +-
 polly/test/ScopInliner/invariant-load-func.ll |   5 +-
 polly/test/ScopInliner/simple-inline-loop.ll  |   3 +-
 9 files changed, 184 insertions(+), 71 deletions(-)
 create mode 100644 polly/include/polly/ScopInliner.h

diff --git a/polly/docs/ReleaseNotes.rst b/polly/docs/ReleaseNotes.rst
index f7c9689089be2..f5ea47b69cf02 100644
--- a/polly/docs/ReleaseNotes.rst
+++ b/polly/docs/ReleaseNotes.rst
@@ -11,3 +11,5 @@ In Polly |version| the following important changes have been incorporated.
     the new features that have recently been committed to our development
     branch.
 
+ * ScopInliner has been updated for the New Pass Manager.
+
diff --git a/polly/include/polly/LinkAllPasses.h b/polly/include/polly/LinkAllPasses.h
index 54e7c5a43ab93..65846653f98e5 100644
--- a/polly/include/polly/LinkAllPasses.h
+++ b/polly/include/polly/LinkAllPasses.h
@@ -120,7 +120,7 @@ struct PollyForcePassLinking {
 
 namespace llvm {
 void initializeCodePreparationPass(llvm::PassRegistry &);
-void initializeScopInlinerPass(llvm::PassRegistry &);
+void initializeScopInlinerWrapperPassPass(llvm::PassRegistry &);
 void initializeScopDetectionWrapperPassPass(llvm::PassRegistry &);
 void initializeScopDetectionPrinterLegacyPassPass(llvm::PassRegistry &);
 void initializeScopInfoRegionPassPass(PassRegistry &);
diff --git a/polly/include/polly/ScopInliner.h b/polly/include/polly/ScopInliner.h
new file mode 100644
index 0000000000000..014667804330f
--- /dev/null
+++ b/polly/include/polly/ScopInliner.h
@@ -0,0 +1,34 @@
+//===------ ScopInliner.h ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef POLLY_POLLYINLINER_H
+#define POLLY_POLLYINLINER_H
+
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/IR/PassManager.h"
+
+namespace polly {
+class ScopInlinerPass : public llvm::PassInfoMixin<ScopInlinerPass> {
+public:
+  ScopInlinerPass();
+
+  llvm::PreservedAnalyses run(llvm::LazyCallGraph::SCC &C,
+                              llvm::CGSCCAnalysisManager &AM,
+                              llvm::LazyCallGraph &CG,
+                              llvm::CGSCCUpdateResult &UR);
+};
+
+llvm::Pass *createScopInlinerWrapperPass();
+} // namespace polly
+
+namespace llvm {
+void initializeScopInlinerWrapperPassPass(llvm::PassRegistry &);
+}
+
+#endif /* POLLY_POLLYINLINER_H */
diff --git a/polly/lib/Support/PollyPasses.def b/polly/lib/Support/PollyPasses.def
index e068f31fdb703..2c792a5867100 100644
--- a/polly/lib/Support/PollyPasses.def
+++ b/polly/lib/Support/PollyPasses.def
@@ -1,3 +1,9 @@
+#ifndef CGSCC_PASS
+#define CGSCC_PASS(NAME, CREATE_PASS, PARSER)
+#endif
+CGSCC_PASS("polly-inline", ScopInlinerPass(), parseNoOptions)
+#undef CGSCC_PASS
+
 #ifndef FUNCTION_ANALYSIS
 #define FUNCTION_ANALYSIS(NAME, CREATE_PASS)
 #endif
diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp
index a46e61aafbeb7..3ace336cb588b 100644
--- a/polly/lib/Support/RegisterPasses.cpp
+++ b/polly/lib/Support/RegisterPasses.cpp
@@ -35,6 +35,7 @@
 #include "polly/ScopDetection.h"
 #include "polly/ScopGraphPrinter.h"
 #include "polly/ScopInfo.h"
+#include "polly/ScopInliner.h"
 #include "polly/Simplify.h"
 #include "polly/Support/DumpFunctionPass.h"
 #include "polly/Support/DumpModulePass.h"
@@ -46,10 +47,13 @@
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Passes/PassPlugin.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Transforms/IPO.h"
 
+using namespace llvm;
 namespace cl = llvm::cl;
+using namespace polly;
 
 using llvm::FunctionPassManager;
 using llvm::OptimizationLevel;
@@ -233,7 +237,7 @@ void initializePollyPasses(llvm::PassRegistry &Registry) {
   initializePollyCanonicalizePass(Registry);
   initializeScopDetectionWrapperPassPass(Registry);
   initializeScopDetectionPrinterLegacyPassPass(Registry);
-  initializeScopInlinerPass(Registry);
+  initializeScopInlinerWrapperPassPass(Registry);
   initializeScopInfoRegionPassPass(Registry);
   initializeScopInfoPrinterLegacyRegionPassPass(Registry);
   initializeScopInfoWrapperPassPass(Registry);
@@ -434,6 +438,16 @@ static void buildLatePollyPipeline(FunctionPassManager &PM,
         false);
 }
 
+static llvm::Expected<std::monostate> parseNoOptions(StringRef Params) {
+  if (!Params.empty())
+    return make_error<StringError>(
+        formatv("'{0}' passed to pass that does not take any options", Params)
+            .str(),
+        inconvertibleErrorCode());
+
+  return std::monostate{};
+}
+
 static OwningScopAnalysisManagerFunctionProxy
 createScopAnalyses(FunctionAnalysisManager &FAM,
                    PassInstrumentationCallbacks *PIC) {
@@ -461,6 +475,25 @@ static void registerFunctionAnalyses(FunctionAnalysisManager &FAM,
   FAM.registerPass([&FAM, PIC] { return createScopAnalyses(FAM, PIC); });
 }
 
+static llvm::Expected<bool>
+parseCGPipeline(StringRef Name, llvm::CGSCCPassManager &CGPM,
+                PassInstrumentationCallbacks *PIC,
+                ArrayRef<PassBuilder::PipelineElement> Pipeline) {
+  assert(Pipeline.empty());
+
+#define CGSCC_PASS(NAME, CREATE_PASS, PARSER)                                  \
+  if (PassBuilder::checkParametrizedPassName(Name, NAME)) {                    \
+    auto Params = PassBuilder::parsePassParameters(PARSER, Name, NAME);        \
+    if (!Params)                                                               \
+      return Params.takeError();                                               \
+    CGPM.addPass(CREATE_PASS);                                                 \
+    return true;                                                               \
+  }
+#include "PollyPasses.def"
+
+  return false;
+}
+
 static bool
 parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
                       ArrayRef<PassBuilder::PipelineElement> Pipeline) {
@@ -590,6 +623,12 @@ parseTopLevelPipeline(llvm::ModulePassManager &MPM,
 /// handle LICMed code to make it useful.
 void registerPollyPasses(PassBuilder &PB) {
   PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks();
+  PB.registerPipelineParsingCallback(
+      [PIC](StringRef Name, CGSCCPassManager &CGPM,
+            ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
+        ExitOnError Err("Unable to parse Polly call graph pass: ");
+        return Err(parseCGPipeline(Name, CGPM, PIC, Pipeline));
+      });
   PB.registerAnalysisRegistrationCallback([PIC](FunctionAnalysisManager &FAM) {
     registerFunctionAnalyses(FAM, PIC);
   });
diff --git a/polly/lib/Transform/ScopInliner.cpp b/polly/lib/Transform/ScopInliner.cpp
index b78206c1e40ba..c04ba3498339e 100644
--- a/polly/lib/Transform/ScopInliner.cpp
+++ b/polly/lib/Transform/ScopInliner.cpp
@@ -13,10 +13,14 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "polly/LinkAllPasses.h"
+#include "polly/ScopInliner.h"
 #include "polly/ScopDetection.h"
+#include "polly/ScopInliner.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Analysis/RegionInfo.h"
+#include "llvm/IR/Dominators.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -28,13 +32,77 @@ using namespace llvm;
 using namespace polly;
 
 namespace {
-class ScopInliner final : public CallGraphSCCPass {
+
+/// Inliner implementation that works with both, LPM (using SCC_t=CallGraph) and
+/// NPM (using SCC_t=LazyCallGraph::SCC)
+template <typename SCC_t> bool runScopInlinerImpl(Function *F, SCC_t &SCC) {
+  // We do not try to inline non-trivial SCCs because this would lead to
+  // "infinite" inlining if we are not careful.
+  if (SCC.size() > 1)
+    return false;
+  assert(SCC.size() == 1 && "found empty SCC");
+
+  // If the function is a nullptr, or the function is a declaration.
+  if (!F)
+    return false;
+  if (F->isDeclaration()) {
+    POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
+                       << "because it is a declaration.\n");
+    return false;
+  }
+
+  PassBuilder PB;
+  // Populate analysis managers and register Polly-specific analyses.
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  auto &DT = FAM.getResult<DominatorTreeAnalysis>(*F);
+  auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(*F);
+  auto &LI = FAM.getResult<LoopAnalysis>(*F);
+  auto &RI = FAM.getResult<RegionInfoAnalysis>(*F);
+  auto &AA = FAM.getResult<AAManager>(*F);
+  auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
+  ScopDetection SD(DT, SE, LI, RI, AA, ORE);
+  SD.detect(*F);
+
+  const bool HasScopAsTopLevelRegion =
+      SD.ValidRegions.contains(RI.getTopLevelRegion());
+
+  bool Changed = false;
+  if (HasScopAsTopLevelRegion) {
+    POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
+                       << " has scop as top level region");
+    F->addFnAttr(llvm::Attribute::AlwaysInline);
+
+    ModulePassManager MPM;
+    MPM.addPass(AlwaysInlinerPass());
+    Module *M = F->getParent();
+    assert(M && "Function has illegal module");
+    PreservedAnalyses PA = MPM.run(*M, MAM);
+    if (!PA.areAllPreserved())
+      Changed = true;
+  } else {
+    POLLY_DEBUG(dbgs() << F->getName()
+                       << " does NOT have scop as top level region\n");
+  }
+
+  return Changed;
+}
+
+class ScopInlinerWrapperPass final : public CallGraphSCCPass {
   using llvm::Pass::doInitialization;
 
 public:
   static char ID;
 
-  ScopInliner() : CallGraphSCCPass(ID) {}
+  ScopInlinerWrapperPass() : CallGraphSCCPass(ID) {}
 
   bool doInitialization(CallGraph &CG) override {
     if (!polly::PollyAllowFullFunction) {
@@ -50,60 +118,8 @@ class ScopInliner final : public CallGraphSCCPass {
   }
 
   bool runOnSCC(CallGraphSCC &SCC) override {
-    // We do not try to inline non-trivial SCCs because this would lead to
-    // "infinite" inlining if we are not careful.
-    if (SCC.size() > 1)
-      return false;
-    assert(SCC.size() == 1 && "found empty SCC");
     Function *F = (*SCC.begin())->getFunction();
-
-    // If the function is a nullptr, or the function is a declaration.
-    if (!F)
-      return false;
-    if (F->isDeclaration()) {
-      POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
-                         << "because it is a declaration.\n");
-      return false;
-    }
-
-    PassBuilder PB;
-    // Populate analysis managers and register Polly-specific analyses.
-    LoopAnalysisManager LAM;
-    FunctionAnalysisManager FAM;
-    CGSCCAnalysisManager CGAM;
-    ModuleAnalysisManager MAM;
-    FAM.registerPass([] { return ScopAnalysis(); });
-    PB.registerModuleAnalyses(MAM);
-    PB.registerCGSCCAnalyses(CGAM);
-    PB.registerFunctionAnalyses(FAM);
-    PB.registerLoopAnalyses(LAM);
-    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
-
-    RegionInfo &RI = FAM.getResult<RegionInfoAnalysis>(*F);
-    ScopDetection &SD = FAM.getResult<ScopAnalysis>(*F);
-
-    const bool HasScopAsTopLevelRegion =
-        SD.ValidRegions.contains(RI.getTopLevelRegion());
-
-    bool Changed = false;
-    if (HasScopAsTopLevelRegion) {
-      POLLY_DEBUG(dbgs() << "Skipping " << F->getName()
-                         << " has scop as top level region");
-      F->addFnAttr(llvm::Attribute::AlwaysInline);
-
-      ModulePassManager MPM;
-      MPM.addPass(AlwaysInlinerPass());
-      Module *M = F->getParent();
-      assert(M && "Function has illegal module");
-      PreservedAnalyses PA = MPM.run(*M, MAM);
-      if (!PA.areAllPreserved())
-        Changed = true;
-    } else {
-      POLLY_DEBUG(dbgs() << F->getName()
-                         << " does NOT have scop as top level region\n");
-    }
-
-    return Changed;
+    return runScopInlinerImpl(F, SCC);
   };
 
   void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -111,18 +127,39 @@ class ScopInliner final : public CallGraphSCCPass {
   }
 };
 } // namespace
-char ScopInliner::ID;
+char ScopInlinerWrapperPass::ID;
 
-Pass *polly::createScopInlinerPass() {
-  ScopInliner *pass = new ScopInliner();
+Pass *polly::createScopInlinerWrapperPass() {
+  ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass();
   return pass;
 }
 
 INITIALIZE_PASS_BEGIN(
-    ScopInliner, "polly-scop-inliner",
+    ScopInlinerWrapperPass, "polly-scop-inliner",
     "inline functions based on how much of the function is a scop.", false,
     false)
 INITIALIZE_PASS_END(
-    ScopInliner, "polly-scop-inliner",
+    ScopInlinerWrapperPass, "polly-scop-inliner",
     "inline functions based on how much of the function is a scop.", false,
     false)
+
+polly::ScopInlinerPass::ScopInlinerPass() {
+  if (!polly::PollyAllowFullFunction) {
+    report_fatal_error(
+        "Aborting from ScopInliner because it only makes sense to run with "
+        "-polly-allow-full-function. "
+        "The heurtistic for ScopInliner checks that the full function is a "
+        "Scop, which happens if and only if polly-allow-full-function is "
+        " enabled. "
+        " If not, the entry block is not included in the Scop");
+  }
+}
+
+PreservedAnalyses polly::ScopInlinerPass::run(llvm::LazyCallGraph::SCC &SCC,
+                                              llvm::CGSCCAnalysisManager &AM,
+                                              llvm::LazyCallGraph &CG,
+                                              llvm::CGSCCUpdateResult &UR) {
+  Function *F = &SCC.begin()->getFunction();
+  bool Changed = runScopInlinerImpl(F, SCC);
+  return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
+}
diff --git a/polly/test/ScopInliner/ignore-declares.ll b/polly/test/ScopInliner/ignore-declares.ll
index 11722dcb32166..5c0cfa103f0bf 100644
--- a/polly/test/ScopInliner/ignore-declares.ll
+++ b/polly/test/ScopInliner/ignore-declares.ll
@@ -1,5 +1,4 @@
-; RUN: opt %loadPolly -polly-detect-full-functions -polly-scop-inliner \
-; RUN: -polly-scops -disable-output < %s
+; RUN: opt %loadNPMPolly -polly-detect-full-functions '-passes=cgscc(polly-inline),function(print<polly-function-scops>)' -disable-output < %s
 
 ; Check that we do not crash if there are declares. We should skip function
 ; declarations and not try to query for domtree.
diff --git a/polly/test/ScopInliner/invariant-load-func.ll b/polly/test/ScopInliner/invariant-load-func.ll
index ffd2ec9cdb60f..58c556a455fb9 100644
--- a/polly/test/ScopInliner/invariant-load-func.ll
+++ b/polly/test/ScopInliner/invariant-load-func.ll
@@ -1,12 +1,9 @@
-; RUN: opt %loadNPMPolly -polly-detect-full-functions -polly-scop-inliner \
-; RUN: -polly-invariant-load-hoisting '-passes=print<polly-function-scops>' -disable-output < %s | FileCheck %s
+; RUN: opt %loadNPMPolly -polly-detect-full-functions -polly-invariant-load-hoisting '-passes=cgscc(polly-inline),function(print<polly-function-scops>)' -disable-output < %s 2>&1 | FileCheck %s
 
 ; Check that we inline a function that requires invariant load hoisting
 ; correctly.
 ; CHECK:    Max Loop Depth:  2
 
-; REQUIRES: pollyacc
-
 
 ; void to_be_inlined(int A[], int *begin, int *end) {
 ;     for(int i = *begin; i < *end; i++) {
diff --git a/polly/test/ScopInliner/simple-inline-loop.ll b/polly/test/ScopInliner/simple-inline-loop.ll
index a5e3483edad05..f12798a3d831a 100644
--- a/polly/test/ScopInliner/simple-inline-loop.ll
+++ b/polly/test/ScopInliner/simple-inline-loop.ll
@@ -1,5 +1,4 @@
-; RUN: opt %loadPolly -polly-detect-full-functions -polly-scop-inliner \
-; RUN: -polly-print-scops -disable-output < %s | FileCheck %s
+; RUN: opt %loadNPMPolly -polly-detect-full-functions '-passes=cgscc(polly-inline),function(print<polly-function-scops>)' -disable-output < %s  2>&1 | FileCheck %s
 
 ; Check that we get the 2 nested loops by inlining `to_be_inlined` into
 ; `inline_site`.

>From 8705fdc402b91a068e7a5025cbd38d4a6e14655b Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Tue, 4 Feb 2025 22:02:51 +0100
Subject: [PATCH 3/4] Sort registerPipelineParsingCallback

---
 polly/lib/Support/RegisterPasses.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp
index 3ace336cb588b..ad37760780c08 100644
--- a/polly/lib/Support/RegisterPasses.cpp
+++ b/polly/lib/Support/RegisterPasses.cpp
@@ -623,12 +623,6 @@ parseTopLevelPipeline(llvm::ModulePassManager &MPM,
 /// handle LICMed code to make it useful.
 void registerPollyPasses(PassBuilder &PB) {
   PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks();
-  PB.registerPipelineParsingCallback(
-      [PIC](StringRef Name, CGSCCPassManager &CGPM,
-            ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
-        ExitOnError Err("Unable to parse Polly call graph pass: ");
-        return Err(parseCGPipeline(Name, CGPM, PIC, Pipeline));
-      });
   PB.registerAnalysisRegistrationCallback([PIC](FunctionAnalysisManager &FAM) {
     registerFunctionAnalyses(FAM, PIC);
   });
@@ -638,6 +632,12 @@ void registerPollyPasses(PassBuilder &PB) {
             ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
         return parseScopPipeline(Name, FPM, PIC, Pipeline);
       });
+  PB.registerPipelineParsingCallback(
+      [PIC](StringRef Name, CGSCCPassManager &CGPM,
+            ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {
+        ExitOnError Err("Unable to parse Polly call graph pass: ");
+        return Err(parseCGPipeline(Name, CGPM, PIC, Pipeline));
+      });
   PB.registerParseTopLevelPipelineCallback(
       [PIC](llvm::ModulePassManager &MPM,
             ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool {

>From 1acf246bac1428358ae616cc846bc40c1ae2b3c3 Mon Sep 17 00:00:00 2001
From: Michael Kruse <llvm-project at meinersbur.de>
Date: Sun, 18 May 2025 01:43:00 +0200
Subject: [PATCH 4/4] Refactor common code of LPM and NPM

---
 polly/lib/Transform/CodePreparation.cpp | 45 +++++++++++++++----------
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/polly/lib/Transform/CodePreparation.cpp b/polly/lib/Transform/CodePreparation.cpp
index 7c8579eb93218..d045fb6b62c90 100644
--- a/polly/lib/Transform/CodePreparation.cpp
+++ b/polly/lib/Transform/CodePreparation.cpp
@@ -27,6 +27,26 @@
 using namespace llvm;
 using namespace polly;
 
+static bool runCodePreprationImpl(Function &F, DominatorTree *DT, LoopInfo *LI,
+                                  RegionInfo *RI) {
+  // Find first non-alloca instruction. Every basic block has a non-alloca
+  // instruction, as every well formed basic block has a terminator.
+  auto &EntryBlock = F.getEntryBlock();
+  BasicBlock::iterator I = EntryBlock.begin();
+  while (isa<AllocaInst>(I))
+    ++I;
+
+  // Abort if not necessary to split
+  if (I->isTerminator() && isa<BranchInst>(I) &&
+      cast<BranchInst>(I)->isUnconditional())
+    return false;
+
+  // splitBlock updates DT, LI and RI.
+  splitEntryBlockForAlloca(&EntryBlock, DT, LI, RI);
+
+  return true;
+}
+
 namespace {
 
 /// Prepare the IR for the scop detection.
@@ -35,9 +55,6 @@ class CodePreparation final : public FunctionPass {
   CodePreparation(const CodePreparation &) = delete;
   const CodePreparation &operator=(const CodePreparation &) = delete;
 
-  LoopInfo *LI;
-  ScalarEvolution *SE;
-
   void clear();
 
 public:
@@ -58,19 +75,11 @@ class CodePreparation final : public FunctionPass {
 
 PreservedAnalyses CodePreparationPass::run(Function &F,
                                            FunctionAnalysisManager &FAM) {
-
-  // Find first non-alloca instruction. Every basic block has a non-alloca
-  // instruction, as every well formed basic block has a terminator.
-  auto &EntryBlock = F.getEntryBlock();
-  BasicBlock::iterator I = EntryBlock.begin();
-  while (isa<AllocaInst>(I))
-    ++I;
-
   auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
   auto &LI = FAM.getResult<LoopAnalysis>(F);
-
-  // splitBlock updates DT, LI and RI.
-  splitEntryBlockForAlloca(&EntryBlock, &DT, &LI, nullptr);
+  bool Changed = runCodePreprationImpl(F, &DT, &LI, nullptr);
+  if (!Changed)
+    return PreservedAnalyses::all();
 
   PreservedAnalyses PA;
   PA.preserve<DominatorTreeAnalysis>();
@@ -84,7 +93,6 @@ CodePreparation::~CodePreparation() { clear(); }
 
 void CodePreparation::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.addRequired<LoopInfoWrapperPass>();
-  AU.addRequired<ScalarEvolutionWrapperPass>();
 
   AU.addPreserved<LoopInfoWrapperPass>();
   AU.addPreserved<RegionInfoPass>();
@@ -96,10 +104,11 @@ bool CodePreparation::runOnFunction(Function &F) {
   if (skipFunction(F))
     return false;
 
-  LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
-  SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
+  DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+  LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+  RegionInfo *RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
 
-  splitEntryBlockForAlloca(&F.getEntryBlock(), this);
+  runCodePreprationImpl(F, DT, LI, RI);
 
   return true;
 }



More information about the llvm-commits mailing list