Skip to content

[Passes] Generalize ShouldRunExtraVectorPasses to allow re-use (NFCI). #118323

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 9 additions & 34 deletions llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/ExtraPassManager.h"

namespace llvm {

Expand All @@ -21,40 +22,6 @@ class Loop;
class StringRef;
class raw_ostream;

struct ShouldRunExtraSimpleLoopUnswitch
: public AnalysisInfoMixin<ShouldRunExtraSimpleLoopUnswitch> {
static AnalysisKey Key;
struct Result {
bool invalidate(Loop &L, const PreservedAnalyses &PA,
LoopAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise,
// it remains preserved.
auto PAC = PA.getChecker<ShouldRunExtraSimpleLoopUnswitch>();
return !PAC.preservedWhenStateless();
}
};

Result run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR) {
return Result();
}

static bool isRequired() { return true; }
};

struct ExtraSimpleLoopUnswitchPassManager : public LoopPassManager {
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U) {
auto PA = PreservedAnalyses::all();
if (AM.getCachedResult<ShouldRunExtraSimpleLoopUnswitch>(L))
PA.intersect(LoopPassManager::run(L, AM, AR, U));
PA.abandon<ShouldRunExtraSimpleLoopUnswitch>();
return PA;
}

static bool isRequired() { return true; }
};

/// This pass transforms loops that contain branches or switches on loop-
/// invariant conditions to have multiple loops. For example, it turns the left
/// into the right code:
Expand Down Expand Up @@ -113,6 +80,14 @@ class SimpleLoopUnswitchPass : public PassInfoMixin<SimpleLoopUnswitchPass> {
function_ref<StringRef(StringRef)> MapClassName2PassName);
};

/// A marker analysis to determine if SimpleLoopUnswitch should run again on a
/// given loop.
struct ShouldRunExtraSimpleLoopUnswitch
: public ShouldRunExtraPasses<ShouldRunExtraSimpleLoopUnswitch>,
public AnalysisInfoMixin<ShouldRunExtraSimpleLoopUnswitch> {
static AnalysisKey Key;
};

} // end namespace llvm

#endif // LLVM_TRANSFORMS_SCALAR_SIMPLELOOPUNSWITCH_H
85 changes: 85 additions & 0 deletions llvm/include/llvm/Transforms/Utils/ExtraPassManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//===- ExtraFunctionPassManager.h - Run Optimizations on Demand -*- C++ -*-===//
//
Copy link
Contributor

Choose a reason for hiding this comment

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

Two empty lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Single line now, thanks

// 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
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file provides a pass manager that only runs its passes if the
/// provided marker analysis has been preserved, together with a class to
/// define such a marker analysis.
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H
#define LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H

#include "llvm/IR/PassManager.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"

namespace llvm {

/// A marker analysis to determine if extra passes should be run on demand.
/// Passes requesting extra transformations to run need to request and preserve
/// this analysis.
template <typename MarkerTy> struct ShouldRunExtraPasses {
struct Result {
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise,
// it remains preserved.
auto PAC = PA.getChecker<MarkerTy>();
return !PAC.preservedWhenStateless();
}

bool invalidate(Loop &L, const PreservedAnalyses &PA,
LoopAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise,
// it remains preserved.
auto PAC = PA.getChecker<MarkerTy>();
return !PAC.preservedWhenStateless();
}
};

Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }

Result run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR) {
return Result();
}
};

/// A pass manager to run a set of extra function passes if the
/// ShouldRunExtraPasses marker analysis is present. This allows passes to
/// request additional transformations on demand. An example is extra
/// simplifications after loop-vectorization, if runtime checks have been added.
template <typename MarkerTy>
struct ExtraFunctionPassManager : public FunctionPassManager {
Copy link
Contributor

Choose a reason for hiding this comment

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

the new pass manager data structures very much do not endorse overriding methods via inheritance. I'd prefer ExtraFunctionPassManager to have a FunctionPassManager member instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I put up #119348, is that what you had in mind?

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
auto PA = PreservedAnalyses::all();
if (AM.getCachedResult<MarkerTy>(F))
PA.intersect(FunctionPassManager::run(F, AM));
PA.abandon<MarkerTy>();
return PA;
}
};

/// A pass manager to run a set of extra loop passes if the MarkerTy analysis is
/// present. This allows passes to request additional transformations on demand.
/// An example is doing additional runs of SimpleLoopUnswitch.
template <typename MarkerTy>
struct ExtraLoopPassManager : public LoopPassManager {
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
LoopStandardAnalysisResults &AR, LPMUpdater &U) {
auto PA = PreservedAnalyses::all();
if (AM.getCachedResult<MarkerTy>(L))
PA.intersect(LoopPassManager::run(L, AM, AR, U));
PA.abandon<MarkerTy>();
return PA;
}
};

} // namespace llvm

#endif // LLVM_TRANSFORMS_UTILS_EXTRAPASSMANAGER_H
40 changes: 8 additions & 32 deletions llvm/include/llvm/Transforms/Vectorize/LoopVectorize.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

#include "llvm/IR/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/ExtraPassManager.h"
#include <functional>

namespace llvm {
Expand All @@ -80,38 +81,6 @@ class TargetTransformInfo;
extern cl::opt<bool> EnableLoopInterleaving;
extern cl::opt<bool> EnableLoopVectorization;

/// A marker to determine if extra passes after loop vectorization should be
/// run.
struct ShouldRunExtraVectorPasses
: public AnalysisInfoMixin<ShouldRunExtraVectorPasses> {
static AnalysisKey Key;
struct Result {
bool invalidate(Function &F, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
// Check whether the analysis has been explicitly invalidated. Otherwise,
// it remains preserved.
auto PAC = PA.getChecker<ShouldRunExtraVectorPasses>();
return !PAC.preservedWhenStateless();
}
};

Result run(Function &F, FunctionAnalysisManager &FAM) { return Result(); }
};

/// A pass manager to run a set of extra function simplification passes after
/// vectorization, if requested. LoopVectorize caches the
/// ShouldRunExtraVectorPasses analysis to request extra simplifications, if
/// they could be beneficial.
struct ExtraVectorPassManager : public FunctionPassManager {
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
auto PA = PreservedAnalyses::all();
if (AM.getCachedResult<ShouldRunExtraVectorPasses>(F))
PA.intersect(FunctionPassManager::run(F, AM));
PA.abandon<ShouldRunExtraVectorPasses>();
return PA;
}
};

struct LoopVectorizeOptions {
/// If false, consider all loops for interleaving.
/// If true, only loops that explicitly request interleaving are considered.
Expand Down Expand Up @@ -201,6 +170,13 @@ void reportVectorizationFailure(const StringRef DebugMsg,
const StringRef OREMsg, const StringRef ORETag,
OptimizationRemarkEmitter *ORE, Loop *TheLoop, Instruction *I = nullptr);

/// A marker analysis to determine if extra passes should be run after loop
/// vectorization.
struct ShouldRunExtraVectorPasses
: public ShouldRunExtraPasses<ShouldRunExtraVectorPasses>,
public AnalysisInfoMixin<ShouldRunExtraVectorPasses> {
static AnalysisKey Key;
};
} // end namespace llvm

#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZE_H
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@
#include "llvm/Transforms/Utils/DXILUpgrade.h"
#include "llvm/Transforms/Utils/Debugify.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/ExtraPassManager.h"
#include "llvm/Transforms/Utils/FixIrreducible.h"
#include "llvm/Transforms/Utils/HelloWorld.h"
#include "llvm/Transforms/Utils/IRNormalizer.h"
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Passes/PassBuilderPipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
#include "llvm/Transforms/Utils/CountVisits.h"
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
#include "llvm/Transforms/Utils/ExtraPassManager.h"
#include "llvm/Transforms/Utils/InjectTLIMappings.h"
#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
#include "llvm/Transforms/Utils/Mem2Reg.h"
Expand Down Expand Up @@ -660,7 +661,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
LPM2.addPass(IndVarSimplifyPass());

{
ExtraSimpleLoopUnswitchPassManager ExtraPasses;
ExtraLoopPassManager<ShouldRunExtraSimpleLoopUnswitch> ExtraPasses;
ExtraPasses.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ Level ==
OptimizationLevel::O3));
LPM2.addPass(std::move(ExtraPasses));
Expand Down Expand Up @@ -1307,7 +1308,7 @@ void PassBuilder::addVectorPasses(OptimizationLevel Level,
FPM.addPass(InstCombinePass());

if (Level.getSpeedupLevel() > 1 && ExtraVectorizerPasses) {
ExtraVectorPassManager ExtraPasses;
ExtraFunctionPassManager<ShouldRunExtraVectorPasses> ExtraPasses;
// At higher optimization levels, try to clean up any runtime overlap and
// alignment checks inserted by the vectorizer. We want to track correlated
// runtime checks for two inner loops in the same outer loop, fold any
Expand Down
Loading