From 7a98df7f74f7ffc94f1684ad4b8dfb056fbcd787 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 24 Jan 2015 04:19:17 +0000 Subject: [PATCH] [PM] Port instcombine to the new pass manager! This is exciting as this is a much more involved port. This is a complex, existing transformation pass. All of the core logic is shared between both old and new pass managers. Only the access to the analyses is separate because the actual techniques are separate. This also uses a bunch of different and interesting analyses and is the first time where we need to use an analysis across an IR layer. This also paves the way to expose instcombine utility functions. I've got a static function that implements the core pass logic over a function which might be mildly interesting, but more interesting is likely exposing a routine which just uses instructions *already in* the worklist and combines until empty. I've switched one of my favorite instcombine tests to run with both as well to make sure this keeps working. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226987 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../llvm/Transforms/InstCombine/InstCombine.h | 46 +++++++++ .../InstCombine/InstCombineWorklist.h | 13 ++- .../InstCombine/InstCombineInternal.h | 2 +- .../InstCombine/InstructionCombining.cpp | 99 ++++++++++++------- test/Transforms/InstCombine/load.ll | 1 + tools/opt/PassRegistry.def | 1 + tools/opt/Passes.cpp | 1 + 7 files changed, 125 insertions(+), 38 deletions(-) create mode 100644 include/llvm/Transforms/InstCombine/InstCombine.h rename {lib => include/llvm}/Transforms/InstCombine/InstCombineWorklist.h (88%) diff --git a/include/llvm/Transforms/InstCombine/InstCombine.h b/include/llvm/Transforms/InstCombine/InstCombine.h new file mode 100644 index 00000000000..f48ec13107b --- /dev/null +++ b/include/llvm/Transforms/InstCombine/InstCombine.h @@ -0,0 +1,46 @@ +//===- InstCombine.h - InstCombine pass -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides the primary interface to the instcombine pass. This pass +/// is suitable for use in the new pass manager. For a pass that works with the +/// legacy pass manager, please look for \c createInstructionCombiningPass() in +/// Scalar.h. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H +#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINE_H + +#include "llvm/IR/Function.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Transforms/InstCombine/InstCombineWorklist.h" + +namespace llvm { + +class InstCombinePass { + InstCombineWorklist Worklist; + +public: + static StringRef name() { return "InstCombinePass"; } + + // Explicitly define constructors for MSVC. + InstCombinePass() {} + InstCombinePass(InstCombinePass &&Arg) : Worklist(std::move(Arg.Worklist)) {} + InstCombinePass &operator=(InstCombinePass &&RHS) { + Worklist = std::move(RHS.Worklist); + return *this; + } + + PreservedAnalyses run(Function &F, AnalysisManager *AM); +}; + +} + +#endif diff --git a/lib/Transforms/InstCombine/InstCombineWorklist.h b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h similarity index 88% rename from lib/Transforms/InstCombine/InstCombineWorklist.h rename to include/llvm/Transforms/InstCombine/InstCombineWorklist.h index 8d857d0f8e0..720ba138bb7 100644 --- a/lib/Transforms/InstCombine/InstCombineWorklist.h +++ b/include/llvm/Transforms/InstCombine/InstCombineWorklist.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H -#define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H +#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H +#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINEWORKLIST_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" @@ -32,6 +32,15 @@ class LLVM_LIBRARY_VISIBILITY InstCombineWorklist { public: InstCombineWorklist() {} + InstCombineWorklist(InstCombineWorklist &&Arg) + : Worklist(std::move(Arg.Worklist)), + WorklistMap(std::move(Arg.WorklistMap)) {} + InstCombineWorklist &operator=(InstCombineWorklist &&RHS) { + Worklist = std::move(RHS.Worklist); + WorklistMap = std::move(RHS.WorklistMap); + return *this; + } + bool isEmpty() const { return Worklist.empty(); } /// Add - Add the specified instruction to the worklist if it isn't already diff --git a/lib/Transforms/InstCombine/InstCombineInternal.h b/lib/Transforms/InstCombine/InstCombineInternal.h index cd9c9e9d5b5..d12ee09d52f 100644 --- a/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/lib/Transforms/InstCombine/InstCombineInternal.h @@ -15,7 +15,6 @@ #ifndef LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H #define LLVM_LIB_TRANSFORMS_INSTCOMBINE_INSTCOMBINEINTERNAL_H -#include "InstCombineWorklist.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/TargetFolder.h" @@ -27,6 +26,7 @@ #include "llvm/IR/Operator.h" #include "llvm/IR/PatternMatch.h" #include "llvm/Pass.h" +#include "llvm/Transforms/InstCombine/InstCombineWorklist.h" #define DEBUG_TYPE "instcombine" diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index d27801b85b5..9a42d4580b8 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -33,7 +33,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" #include "InstCombineInternal.h" #include "llvm-c/Initialization.h" #include "llvm/ADT/SmallPtrSet.h" @@ -45,6 +45,7 @@ #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/CFG.h" #include "llvm/IR/DataLayout.h" @@ -55,7 +56,7 @@ #include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Local.h" #include #include @@ -2922,6 +2923,66 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout *DL, return MadeIRChange; } +static bool combineInstructionsOverFunction( + Function &F, InstCombineWorklist &Worklist, AssumptionCache &AC, + TargetLibraryInfo &TLI, DominatorTree &DT, const DataLayout *DL = nullptr, + LoopInfo *LI = nullptr) { + // Minimizing size? + bool MinimizeSize = F.getAttributes().hasAttribute( + AttributeSet::FunctionIndex, Attribute::MinSize); + + /// Builder - This is an IRBuilder that automatically inserts new + /// instructions into the worklist when they are created. + IRBuilder Builder( + F.getContext(), TargetFolder(DL), InstCombineIRInserter(Worklist, &AC)); + + // Lower dbg.declare intrinsics otherwise their value may be clobbered + // by instcombiner. + bool DbgDeclaresChanged = LowerDbgDeclare(F); + + // Iterate while there is work to do. + int Iteration = 0; + for (;;) { + ++Iteration; + DEBUG(dbgs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on " + << F.getName() << "\n"); + + bool Changed = false; + if (prepareICWorklistFromFunction(F, DL, &TLI, Worklist)) + Changed = true; + + InstCombiner IC(Worklist, &Builder, MinimizeSize, &AC, &TLI, &DT, DL, LI); + if (IC.run()) + Changed = true; + + if (!Changed) + break; + } + + return DbgDeclaresChanged || Iteration > 1; +} + +PreservedAnalyses InstCombinePass::run(Function &F, + AnalysisManager *AM) { + auto *DL = F.getParent()->getDataLayout(); + + auto &AC = AM->getResult(F); + auto &DT = AM->getResult(F); + auto &TLI = AM->getResult(F); + + auto *LI = AM->getCachedResult(F); + + if (!combineInstructionsOverFunction(F, Worklist, AC, TLI, DT, DL, LI)) + // No changes, all analyses are preserved. + return PreservedAnalyses::all(); + + // Mark all the analyses that instcombine updates as preserved. + // FIXME: Need a way to preserve CFG analyses here! + PreservedAnalyses PA; + PA.preserve(); + return PA; +} + namespace { /// \brief The legacy pass manager's instcombine pass. /// @@ -2954,10 +3015,6 @@ bool InstructionCombiningPass::runOnFunction(Function &F) { if (skipOptnoneFunction(F)) return false; - // Lower dbg.declare intrinsics otherwise their value may be clobbered - // by instcombiner. - bool DbgDeclaresChanged = LowerDbgDeclare(F); - // Required analyses. auto &AC = getAnalysis().getAssumptionCache(F); auto &TLI = getAnalysis().getTLI(); @@ -2969,35 +3026,7 @@ bool InstructionCombiningPass::runOnFunction(Function &F) { auto *LIWP = getAnalysisIfAvailable(); auto *LI = LIWP ? &LIWP->getLoopInfo() : nullptr; - // Minimizing size? - bool MinimizeSize = F.getAttributes().hasAttribute( - AttributeSet::FunctionIndex, Attribute::MinSize); - - /// Builder - This is an IRBuilder that automatically inserts new - /// instructions into the worklist when they are created. - IRBuilder Builder( - F.getContext(), TargetFolder(DL), InstCombineIRInserter(Worklist, &AC)); - - // Iterate while there is work to do. - int Iteration = 0; - for (;;) { - ++Iteration; - DEBUG(dbgs() << "\n\nINSTCOMBINE ITERATION #" << Iteration << " on " - << F.getName() << "\n"); - - bool Changed = false; - if (prepareICWorklistFromFunction(F, DL, &TLI, Worklist)) - Changed = true; - - InstCombiner IC(Worklist, &Builder, MinimizeSize, &AC, &TLI, &DT, DL, LI); - if (IC.run()) - Changed = true; - - if (!Changed) - break; - } - - return DbgDeclaresChanged || Iteration > 1; + return combineInstructionsOverFunction(F, Worklist, AC, TLI, DT, DL, LI); } char InstructionCombiningPass::ID = 0; diff --git a/test/Transforms/InstCombine/load.ll b/test/Transforms/InstCombine/load.ll index 700797ab22c..624083b25ec 100644 --- a/test/Transforms/InstCombine/load.ll +++ b/test/Transforms/InstCombine/load.ll @@ -1,4 +1,5 @@ ; RUN: opt -instcombine -S < %s | FileCheck %s +; RUN: opt -passes=instcombine -S < %s | FileCheck %s ; This test makes sure that these instructions are properly eliminated. diff --git a/tools/opt/PassRegistry.def b/tools/opt/PassRegistry.def index 068495e9903..2c1b36b01fd 100644 --- a/tools/opt/PassRegistry.def +++ b/tools/opt/PassRegistry.def @@ -60,6 +60,7 @@ FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) #ifndef FUNCTION_PASS #define FUNCTION_PASS(NAME, CREATE_PASS) #endif +FUNCTION_PASS("instcombine", InstCombinePass()) FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) FUNCTION_PASS("no-op-function", NoOpFunctionPass()) FUNCTION_PASS("print", PrintFunctionPass(dbgs())) diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index 5488059905e..1788e695d5e 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -25,6 +25,7 @@ #include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" using namespace llvm;