namespace llvm {
+static constexpr unsigned InstCombineDefaultMaxIterations = 1000;
+
+struct InstCombineOptions {
+ bool UseLoopInfo;
+ unsigned MaxIterations;
+
+ InstCombineOptions()
+ : UseLoopInfo(false), MaxIterations(InstCombineDefaultMaxIterations) {}
+
+ InstCombineOptions &setUseLoopInfo(bool Value) {
+ UseLoopInfo = Value;
+ return *this;
+ }
+
+ InstCombineOptions &setMaxIterations(unsigned Value) {
+ MaxIterations = Value;
+ return *this;
+ }
+};
+
class InstCombinePass : public PassInfoMixin<InstCombinePass> {
+private:
InstructionWorklist Worklist;
- const unsigned MaxIterations;
+ InstCombineOptions Options;
public:
- explicit InstCombinePass();
- explicit InstCombinePass(unsigned MaxIterations);
+ explicit InstCombinePass(InstCombineOptions Opts = {});
+ void printPipeline(raw_ostream &OS,
+ function_ref<StringRef(StringRef)> MapClassName2PassName);
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
return Result;
}
+Expected<InstCombineOptions> parseInstCombineOptions(StringRef Params) {
+ InstCombineOptions Result;
+ while (!Params.empty()) {
+ StringRef ParamName;
+ std::tie(ParamName, Params) = Params.split(';');
+
+ bool Enable = !ParamName.consume_front("no-");
+ if (ParamName == "use-loop-info") {
+ Result.setUseLoopInfo(Enable);
+ } else if (Enable && ParamName.consume_front("max-iterations=")) {
+ APInt MaxIterations;
+ if (ParamName.getAsInteger(0, MaxIterations))
+ return make_error<StringError>(
+ formatv("invalid argument to InstCombine pass max-iterations "
+ "parameter: '{0}' ",
+ ParamName).str(),
+ inconvertibleErrorCode());
+ Result.setMaxIterations((unsigned)MaxIterations.getZExtValue());
+ } else {
+ return make_error<StringError>(
+ formatv("invalid InstCombine pass parameter '{0}' ", ParamName).str(),
+ inconvertibleErrorCode());
+ }
+ }
+ return Result;
+}
+
/// Parser of parameters for LoopVectorize pass.
Expected<LoopVectorizeOptions> parseLoopVectorizeOptions(StringRef Params) {
LoopVectorizeOptions Opts;
parseLoopVectorizeOptions,
"no-interleave-forced-only;interleave-forced-only;"
"no-vectorize-forced-only;vectorize-forced-only")
+FUNCTION_PASS_WITH_PARAMS("instcombine",
+ "InstCombinePass",
+ [](InstCombineOptions Opts) {
+ return InstCombinePass(Opts);
+ },
+ parseInstCombineOptions,
+ "no-use-loop-info;use-loop-info;"
+ "max-iterations=N"
+ )
FUNCTION_PASS_WITH_PARAMS("mldst-motion",
"MergedLoadStoreMotionPass",
[](MergedLoadStoreMotionOptions Opts) {
"Controls which instructions are visited");
// FIXME: these limits eventually should be as low as 2.
-static constexpr unsigned InstCombineDefaultMaxIterations = 1000;
#ifndef NDEBUG
static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 100;
#else
"instcombine-max-sink-users", cl::init(32),
cl::desc("Maximum number of undroppable users for instruction sinking"));
-static cl::opt<unsigned> LimitMaxIterations(
- "instcombine-max-iterations",
- cl::desc("Limit the maximum number of instruction combining iterations"),
- cl::init(InstCombineDefaultMaxIterations));
-
static cl::opt<unsigned> InfiniteLoopDetectionThreshold(
"instcombine-infinite-loop-threshold",
cl::desc("Number of instruction combining iterations considered an "
DominatorTree &DT, OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI,
ProfileSummaryInfo *PSI, unsigned MaxIterations, LoopInfo *LI) {
auto &DL = F.getParent()->getDataLayout();
- MaxIterations = std::min(MaxIterations, LimitMaxIterations.getValue());
/// Builder - This is an IRBuilder that automatically inserts new
/// instructions into the worklist when they are created.
return MadeIRChange;
}
-InstCombinePass::InstCombinePass() : MaxIterations(LimitMaxIterations) {}
+InstCombinePass::InstCombinePass(InstCombineOptions Opts) : Options(Opts) {}
-InstCombinePass::InstCombinePass(unsigned MaxIterations)
- : MaxIterations(MaxIterations) {}
+void InstCombinePass::printPipeline(
+ raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
+ static_cast<PassInfoMixin<InstCombinePass> *>(this)->printPipeline(
+ OS, MapClassName2PassName);
+ OS << '<';
+ OS << "max-iterations=" << Options.MaxIterations << ";";
+ OS << (Options.UseLoopInfo ? "" : "no-") << "use-loop-info";
+ OS << '>';
+}
PreservedAnalyses InstCombinePass::run(Function &F,
FunctionAnalysisManager &AM) {
auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
auto &TTI = AM.getResult<TargetIRAnalysis>(F);
+ // TODO: Only use LoopInfo when the option is set. This requires that the
+ // callers in the pass pipeline explicitly set the option.
auto *LI = AM.getCachedResult<LoopAnalysis>(F);
+ if (!LI && Options.UseLoopInfo)
+ LI = &AM.getResult<LoopAnalysis>(F);
auto *AA = &AM.getResult<AAManager>(F);
auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
&AM.getResult<BlockFrequencyAnalysis>(F) : nullptr;
if (!combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE,
- BFI, PSI, MaxIterations, LI))
+ BFI, PSI, Options.MaxIterations, LI))
// No changes, all analyses are preserved.
return PreservedAnalyses::all();
;; Test SeparateConstOffsetFromGEPPass option.
; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='separate-const-offset-from-gep<lower-gep>' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-27
-; CHECK-27: function(separate-const-offset-from-gep<lower-gep>)
\ No newline at end of file
+; CHECK-27: function(separate-const-offset-from-gep<lower-gep>)
+
+;; Test InstCombine options - the first pass checks default settings, and the second checks customized options.
+; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(instcombine,instcombine<use-loop-info;max-iterations=42>)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-28
+; CHECK-28: function(instcombine<max-iterations=1000;no-use-loop-info>,instcombine<max-iterations=42;use-loop-info>)
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -opaque-pointers=0 < %s -passes='require<loops>,instcombine' -S | FileCheck %s
+; RUN: opt -opaque-pointers=0 < %s -passes='instcombine<use-loop-info>' -S | FileCheck %s
+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=instcombine -instcombine-max-iterations=1 -S | FileCheck %s
+; RUN: opt < %s -passes='instcombine<max-iterations=1>' -S | FileCheck %s
; These tests check the optimizations specific to
; pointers being relocated at a statepoint.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=instcombine -instcombine-max-iterations=1 -S | FileCheck %s
+; RUN: opt < %s -passes='instcombine<max-iterations=1>' -S | FileCheck %s
; These tests check the optimizations specific to
; pointers being relocated at a statepoint.