Index: llvm/trunk/include/llvm/Transforms/IPO/HotColdSplitting.h =================================================================== --- llvm/trunk/include/llvm/Transforms/IPO/HotColdSplitting.h +++ llvm/trunk/include/llvm/Transforms/IPO/HotColdSplitting.h @@ -0,0 +1,31 @@ +//===- HotColdSplitting.h ---- Outline Cold Regions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This pass outlines cold regions to a separate function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_HOTCOLDSPLITTING_H +#define LLVM_TRANSFORMS_IPO_HOTCOLDSPLITTING_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Module; + +/// Pass to outline cold regions. +class HotColdSplittingPass : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_HOTCOLDSPLITTING_H + Index: llvm/trunk/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/trunk/lib/Passes/PassBuilder.cpp +++ llvm/trunk/lib/Passes/PassBuilder.cpp @@ -75,6 +75,7 @@ #include "llvm/Transforms/IPO/GlobalDCE.h" #include "llvm/Transforms/IPO/GlobalOpt.h" #include "llvm/Transforms/IPO/GlobalSplit.h" +#include "llvm/Transforms/IPO/HotColdSplitting.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/Inliner.h" #include "llvm/Transforms/IPO/Internalize.h" @@ -198,6 +199,8 @@ EnableCHR("enable-chr-npm", cl::init(true), cl::Hidden, cl::desc("Enable control height reduction optimization (CHR)")); +extern cl::opt EnableHotColdSplit; + static bool isOptimizingForSize(PassBuilder::OptimizationLevel Level) { switch (Level) { case PassBuilder::O0: @@ -614,6 +617,9 @@ true)); } + if (EnableHotColdSplit) + MPM.addPass(HotColdSplittingPass()); + // Interprocedural constant propagation now that basic cleanup has occurred // and prior to optimizing globals. // FIXME: This position in the pipeline hasn't been carefully considered in Index: llvm/trunk/lib/Passes/PassRegistry.def =================================================================== --- llvm/trunk/lib/Passes/PassRegistry.def +++ llvm/trunk/lib/Passes/PassRegistry.def @@ -51,6 +51,7 @@ MODULE_PASS("globaldce", GlobalDCEPass()) MODULE_PASS("globalopt", GlobalOptPass()) MODULE_PASS("globalsplit", GlobalSplitPass()) +MODULE_PASS("hotcoldsplit", HotColdSplittingPass()) MODULE_PASS("inferattrs", InferFunctionAttrsPass()) MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass()) MODULE_PASS("instrprof", InstrProfiling()) Index: llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp +++ llvm/trunk/lib/Transforms/IPO/HotColdSplitting.cpp @@ -44,6 +44,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/HotColdSplitting.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" @@ -409,6 +410,38 @@ return HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M); } +PreservedAnalyses +HotColdSplittingPass::run(Module &M, ModuleAnalysisManager &AM) { + auto &FAM = AM.getResult(M).getManager(); + + std::function GetAssumptionCache = + [&FAM](Function &F) -> AssumptionCache & { + return FAM.getResult(F); + }; + + auto GBFI = [&FAM](Function &F) { + return &FAM.getResult(F); + }; + + std::function GTTI = + [&FAM](Function &F) -> TargetTransformInfo & { + return FAM.getResult(F); + }; + + std::unique_ptr ORE; + std::function GetORE = + [&ORE](Function &F) -> OptimizationRemarkEmitter & { + ORE.reset(new OptimizationRemarkEmitter(&F)); + return *ORE.get(); + }; + + ProfileSummaryInfo *PSI = &AM.getResult(M); + + if (HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M)) + return PreservedAnalyses::none(); + return PreservedAnalyses::all(); +} + char HotColdSplittingLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN(HotColdSplittingLegacyPass, "hotcoldsplit", "Hot Cold Splitting", false, false) Index: llvm/trunk/test/Transforms/HotColdSplit/split-cold-1.ll =================================================================== --- llvm/trunk/test/Transforms/HotColdSplit/split-cold-1.ll +++ llvm/trunk/test/Transforms/HotColdSplit/split-cold-1.ll @@ -1,4 +1,5 @@ ; RUN: opt -hotcoldsplit -S < %s | FileCheck %s +; RUN: opt -passes=hotcoldsplit -S < %s | FileCheck %s ; Outlined function is called from a basic block named codeRepl ; CHECK: codeRepl: Index: llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll =================================================================== --- llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll +++ llvm/trunk/test/Transforms/HotColdSplit/split-cold-2.ll @@ -1,4 +1,5 @@ ; RUN: opt -hotcoldsplit -S < %s +; RUN: opt -passes=hotcoldsplit -S < %s ; Make sure this compiles. This test used to fail with an invalid phi node: the ; two predecessors were outlined and the SSA representation was invalid.