From 3bcaf3f2809410d7f1c87cf9d72753ba94ba63ac Mon Sep 17 00:00:00 2001 From: Michael Kruse 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 CheckParallel("polly-check-parallel", - cl::desc("Check for parallel loops"), - cl::Hidden, cl::cat(PollyCategory)); - -static cl::opt CheckVectorizable("polly-check-vectorizable", - cl::desc("Check for vectorizable loops"), - cl::Hidden, cl::cat(PollyCategory)); - -void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequiredTransitive(); - AU.addRequired(); - AU.addRequiredTransitive(); - AU.setPreservesAll(); -} - -bool PolyhedralInfo::runOnFunction(Function &F) { - DI = &getAnalysis(); - SI = getAnalysis().getSI(); - return false; -} - -void PolyhedralInfo::print(raw_ostream &OS, const Module *) const { - auto &LI = getAnalysis().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(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(); - - 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(); - 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 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 { +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 parseNoOptions(StringRef Params) { + if (!Params.empty()) + return make_error( + 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 +parseCGPipeline(StringRef Name, llvm::CGSCCPassManager &CGPM, + PassInstrumentationCallbacks *PIC, + ArrayRef 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 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 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 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(*F); + auto &SE = FAM.getResult(*F); + auto &LI = FAM.getResult(*F); + auto &RI = FAM.getResult(*F); + auto &AA = FAM.getResult(*F); + auto &ORE = FAM.getResult(*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(*F); - ScopDetection &SD = FAM.getResult(*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)' -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' -disable-output < %s | FileCheck %s +; RUN: opt %loadNPMPolly -polly-detect-full-functions -polly-invariant-load-hoisting '-passes=cgscc(polly-inline),function(print)' -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)' -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 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 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 Pipeline) -> bool { return parseScopPipeline(Name, FPM, PIC, Pipeline); }); + PB.registerPipelineParsingCallback( + [PIC](StringRef Name, CGSCCPassManager &CGPM, + ArrayRef 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 Pipeline) -> bool { From 1acf246bac1428358ae616cc846bc40c1ae2b3c3 Mon Sep 17 00:00:00 2001 From: Michael Kruse 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(I)) + ++I; + + // Abort if not necessary to split + if (I->isTerminator() && isa(I) && + cast(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(I)) - ++I; - auto &DT = FAM.getResult(F); auto &LI = FAM.getResult(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(); @@ -84,7 +93,6 @@ CodePreparation::~CodePreparation() { clear(); } void CodePreparation::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); - AU.addRequired(); AU.addPreserved(); AU.addPreserved(); @@ -96,10 +104,11 @@ bool CodePreparation::runOnFunction(Function &F) { if (skipFunction(F)) return false; - LI = &getAnalysis().getLoopInfo(); - SE = &getAnalysis().getSE(); + DominatorTree *DT = &getAnalysis().getDomTree(); + LoopInfo *LI = &getAnalysis().getLoopInfo(); + RegionInfo *RI = &getAnalysis().getRegionInfo(); - splitEntryBlockForAlloca(&F.getEntryBlock(), this); + runCodePreprationImpl(F, DT, LI, RI); return true; }