Skip to content

Commit

Permalink
[LoopUnroll] add parsing for unroll parameters in -passes pipeline
Browse files Browse the repository at this point in the history
Allow to specify loop-unrolling with optional parameters explicitly
spelled out in -passes pipeline specification.
Introducing somewhat generic way of specifying parameters parsing via
FUNCTION_PASS_PARAMETRIZED pass registration.

Syntax of parametrized unroll pass name is as follows:
   'unroll<' parameter-list '>'

Where parameter-list is ';'-separate list of parameter names and optlevel
   optlevel: 'O[0-3]'
   parameter: { 'partial' | 'peeling' | 'runtime' | 'upperbound' }
   negated:  'no-' parameter

Example:
   -passes=loop(unroll<O3;runtime;no-upperbound>)

    this invokes LoopUnrollPass configured with OptLevel=3,
    Runtime, no UpperBound, everything else by default.

llvm-svn: 350808
  • Loading branch information
Fedor Sergeev committed Jan 10, 2019
1 parent 15313a3 commit b787140
Showing 2 changed files with 104 additions and 2 deletions.
96 changes: 96 additions & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
@@ -1242,6 +1242,91 @@ static Optional<int> parseDevirtPassName(StringRef Name) {
return Count;
}

static bool checkParametrizedPassName(StringRef Name, StringRef PassName) {
if (!Name.consume_front(PassName))
return false;
// normal pass name w/o parameters == default parameters
if (Name.empty())
return true;
return Name.startswith("<") && Name.endswith(">");
}

namespace {

/// This performs customized parsing of pass name with parameters.
///
/// We do not need parametrization of passes in textual pipeline very often,
/// yet on a rare occasion ability to specify parameters right there can be
/// useful.
///
/// \p Name - parameterized specification of a pass from a textual pipeline
/// is a string in a form of :
/// PassName '<' parameter-list '>'
///
/// Parameter list is being parsed by the parser callable argument, \p Parser,
/// It takes a string-ref of parameters and returns either StringError or a
/// parameter list in a form of a custom parameters type, all wrapped into
/// Expected<> template class.
///
template <typename ParametersParseCallableT>
auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name,
StringRef PassName) -> decltype(Parser(StringRef{})) {
using ParametersT = typename decltype(Parser(StringRef{}))::value_type;

StringRef Params = Name;
if (!Params.consume_front(PassName)) {
assert(false &&
"unable to strip pass name from parametrized pass specification");
}
if (Params.empty())
return ParametersT{};
if (!Params.consume_front("<") || !Params.consume_back(">")) {
assert(false && "invalid format for parametrized pass name");
}

Expected<ParametersT> Result = Parser(Params);
assert((Result || Result.template errorIsA<StringError>()) &&
"Pass parameter parser can only return StringErrors.");
return std::move(Result);
}

/// Parser of parameters for LoopUnroll pass.
Expected<LoopUnrollOptions> parseLoopUnrollOptions(StringRef Params) {
LoopUnrollOptions UnrollOpts;
while (!Params.empty()) {
StringRef ParamName;
std::tie(ParamName, Params) = Params.split(';');
int OptLevel = StringSwitch<int>(ParamName)
.Case("O0", 0)
.Case("O1", 1)
.Case("O2", 2)
.Case("O3", 3)
.Default(-1);
if (OptLevel >= 0) {
UnrollOpts.setOptLevel(OptLevel);
continue;
}

bool Enable = !ParamName.consume_front("no-");
if (ParamName == "partial") {
UnrollOpts.setPartial(Enable);
} else if (ParamName == "peeling") {
UnrollOpts.setPeeling(Enable);
} else if (ParamName == "runtime") {
UnrollOpts.setRuntime(Enable);
} else if (ParamName == "upperbound") {
UnrollOpts.setUpperBound(Enable);
} else {
return make_error<StringError>(
formatv("invalid LoopUnrollPass parameter '{0}' ", ParamName).str(),
inconvertibleErrorCode());
}
}
return UnrollOpts;
}

} // namespace

/// Tests whether a pass name starts with a valid prefix for a default pipeline
/// alias.
static bool startsWithDefaultPipelineAliasPrefix(StringRef Name) {
@@ -1337,6 +1422,9 @@ static bool isFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
#define FUNCTION_PASS(NAME, CREATE_PASS) \
if (Name == NAME) \
return true;
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \
if (checkParametrizedPassName(Name, NAME)) \
return true;
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
return true;
@@ -1674,6 +1762,14 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM,
FPM.addPass(CREATE_PASS); \
return Error::success(); \
}
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \
if (checkParametrizedPassName(Name, NAME)) { \
auto Params = parsePassParameters(PARSER, Name, NAME); \
if (!Params) \
return Params.takeError(); \
FPM.addPass(CREATE_PASS(Params.get())); \
return Error::success(); \
}
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
if (Name == "require<" NAME ">") { \
FPM.addPass( \
10 changes: 8 additions & 2 deletions llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
@@ -223,8 +223,6 @@ FUNCTION_PASS("spec-phis", SpeculateAroundPHIsPass())
FUNCTION_PASS("sroa", SROA())
FUNCTION_PASS("tailcallelim", TailCallElimPass())
FUNCTION_PASS("unreachableblockelim", UnreachableBlockElimPass())
FUNCTION_PASS("unroll", LoopUnrollPass())
FUNCTION_PASS("unroll<peeling;no-runtime>",LoopUnrollPass(LoopUnrollOptions().setPeeling(true).setRuntime(false)))
FUNCTION_PASS("verify", VerifierPass())
FUNCTION_PASS("verify<domtree>", DominatorTreeVerifierPass())
FUNCTION_PASS("verify<loops>", LoopVerifierPass())
@@ -236,6 +234,14 @@ FUNCTION_PASS("transform-warning", WarnMissedTransformationsPass())
FUNCTION_PASS("msan", MemorySanitizerPass())
#undef FUNCTION_PASS

#ifndef FUNCTION_PASS_WITH_PARAMS
#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER)
#endif
FUNCTION_PASS_WITH_PARAMS("unroll",
[](LoopUnrollOptions Opts) { return LoopUnrollPass(Opts); },
parseLoopUnrollOptions)
#undef FUNCTION_PASS_WITH_PARAMS

#ifndef LOOP_ANALYSIS
#define LOOP_ANALYSIS(NAME, CREATE_PASS)
#endif

0 comments on commit b787140

Please sign in to comment.