[llvm] r267022 - Initial implementation of optimization bisect support.

Andrew Kaylor via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 21 10:59:13 PDT 2016


Author: akaylor
Date: Thu Apr 21 12:58:54 2016
New Revision: 267022

URL: http://llvm.org/viewvc/llvm-project?rev=267022&view=rev
Log:
Initial implementation of optimization bisect support.

This patch implements a optimization bisect feature, which will allow optimizations to be selectively disabled at compile time in order to track down test failures that are caused by incorrect optimizations.

The bisection is enabled using a new command line option (-opt-bisect-limit).  Individual passes that may be skipped call the OptBisect object (via an LLVMContext) to see if they should be skipped based on the bisect limit.  A finer level of control (disabling individual transformations) can be managed through an addition OptBisect method, but this is not yet used.

The skip checking in this implementation is based on (and replaces) the skipOptnoneFunction check.  Where that check was being called, a new call has been inserted in its place which checks the bisect limit and the optnone attribute.  A new function call has been added for module and SCC passes that behaves in a similar way.

Differential Revision: http://reviews.llvm.org/D19172


Added:
    llvm/trunk/include/llvm/IR/OptBisect.h   (with props)
    llvm/trunk/lib/IR/OptBisect.cpp   (with props)
    llvm/trunk/test/Other/opt-bisect-helper.py   (with props)
    llvm/trunk/test/Other/opt-bisect-legacy-pass-manager.ll
    llvm/trunk/test/Other/opt-bisect-new-pass-manager.ll
Modified:
    llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h
    llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
    llvm/trunk/include/llvm/Analysis/LoopPass.h
    llvm/trunk/include/llvm/IR/LLVMContext.h
    llvm/trunk/include/llvm/Pass.h
    llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp
    llvm/trunk/lib/Analysis/LoopPass.cpp
    llvm/trunk/lib/CodeGen/BranchFolding.cpp
    llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
    llvm/trunk/lib/CodeGen/DeadMachineInstructionElim.cpp
    llvm/trunk/lib/CodeGen/LowerEmuTLS.cpp
    llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp
    llvm/trunk/lib/CodeGen/MachineCSE.cpp
    llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp
    llvm/trunk/lib/CodeGen/MachineLICM.cpp
    llvm/trunk/lib/CodeGen/MachineScheduler.cpp
    llvm/trunk/lib/CodeGen/MachineSink.cpp
    llvm/trunk/lib/CodeGen/OptimizePHIs.cpp
    llvm/trunk/lib/CodeGen/PeepholeOptimizer.cpp
    llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp
    llvm/trunk/lib/CodeGen/StackColoring.cpp
    llvm/trunk/lib/CodeGen/TailDuplication.cpp
    llvm/trunk/lib/IR/CMakeLists.txt
    llvm/trunk/lib/IR/LLVMContext.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.cpp
    llvm/trunk/lib/IR/LLVMContextImpl.h
    llvm/trunk/lib/IR/Pass.cpp
    llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp
    llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp
    llvm/trunk/lib/Transforms/IPO/CrossDSOCFI.cpp
    llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
    llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp
    llvm/trunk/lib/Transforms/IPO/ExtractGV.cpp
    llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
    llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
    llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
    llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
    llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp
    llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp
    llvm/trunk/lib/Transforms/IPO/Inliner.cpp
    llvm/trunk/lib/Transforms/IPO/Internalize.cpp
    llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp
    llvm/trunk/lib/Transforms/IPO/LowerBitSets.cpp
    llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
    llvm/trunk/lib/Transforms/IPO/PartialInlining.cpp
    llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
    llvm/trunk/lib/Transforms/IPO/StripDeadPrototypes.cpp
    llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp
    llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
    llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
    llvm/trunk/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
    llvm/trunk/lib/Transforms/Scalar/ADCE.cpp
    llvm/trunk/lib/Transforms/Scalar/BDCE.cpp
    llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp
    llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
    llvm/trunk/lib/Transforms/Scalar/DCE.cpp
    llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
    llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp
    llvm/trunk/lib/Transforms/Scalar/Float2Int.cpp
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
    llvm/trunk/lib/Transforms/Scalar/LICM.cpp
    llvm/trunk/lib/Transforms/Scalar/LoadCombine.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopLoadElimination.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp
    llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp
    llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp
    llvm/trunk/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp
    llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp
    llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
    llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
    llvm/trunk/lib/Transforms/Scalar/SROA.cpp
    llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
    llvm/trunk/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
    llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp
    llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp
    llvm/trunk/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
    llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
    llvm/trunk/lib/Transforms/Utils/Mem2Reg.cpp
    llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp
    llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
    llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp

Modified: llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h (original)
+++ llvm/trunk/include/llvm/Analysis/CallGraphSCCPass.h Thu Apr 21 12:58:54 2016
@@ -77,15 +77,21 @@ public:
   /// the call graph.  If the derived class implements this method, it should
   /// always explicitly call the implementation here.
   void getAnalysisUsage(AnalysisUsage &Info) const override;
+
+protected:
+  /// Optional passes call this function to check whether the pass should be
+  /// skipped. This is the case when optimization bisect is over the limit.
+  bool skipSCC(CallGraphSCC &SCC) const;
 };
 
 /// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
 class CallGraphSCC {
+  const CallGraph &CG; // The call graph for this SCC.
   void *Context; // The CGPassManager object that is vending this.
   std::vector<CallGraphNode*> Nodes;
 
 public:
-  CallGraphSCC(void *context) : Context(context) {}
+  CallGraphSCC(CallGraph &cg, void *context) : CG(cg), Context(context) {}
 
   void initialize(CallGraphNode *const *I, CallGraphNode *const *E) {
     Nodes.assign(I, E);
@@ -101,6 +107,8 @@ public:
   typedef std::vector<CallGraphNode *>::const_iterator iterator;
   iterator begin() const { return Nodes.begin(); }
   iterator end() const { return Nodes.end(); }
+
+  const CallGraph &getCallGraph() { return CG; }
 };
 
 } // End llvm namespace

Modified: llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LazyCallGraph.h (original)
+++ llvm/trunk/include/llvm/Analysis/LazyCallGraph.h Thu Apr 21 12:58:54 2016
@@ -923,6 +923,15 @@ public:
   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
 };
 
+/// Check with the OptBisect object to determine whether the described pass
+/// should be skipped.
+///
+/// This is a helper function which abstracts the details of accessing OptBisect
+/// through an LLVMContext obtained from an SCC.
+bool skipPassForSCC(const StringRef PassName, const LazyCallGraph::SCC &SCC);
+// This function is implemented in OptBisect.cpp but must be declared
+// here to avoid include file dependency problems.
+
 }
 
 #endif

Modified: llvm/trunk/include/llvm/Analysis/LoopPass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopPass.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LoopPass.h (original)
+++ llvm/trunk/include/llvm/Analysis/LoopPass.h Thu Apr 21 12:58:54 2016
@@ -88,9 +88,10 @@ public:
   virtual void deleteAnalysisLoop(Loop *L) {}
 
 protected:
-  /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
-  /// and most transformation passes should skip it.
-  bool skipOptnoneFunction(const Loop *L) const;
+  /// Optional passes call this function to check whether the pass should be
+  /// skipped. This is the case when Attribute::OptimizeNone is set or when
+  /// optimization bisect is over the limit.
+  bool skipLoop(const Loop *L) const;
 };
 
 class LPPassManager : public FunctionPass, public PMDataManager {

Modified: llvm/trunk/include/llvm/IR/LLVMContext.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LLVMContext.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/LLVMContext.h (original)
+++ llvm/trunk/include/llvm/IR/LLVMContext.h Thu Apr 21 12:58:54 2016
@@ -32,6 +32,7 @@ class DiagnosticInfo;
 template <typename T> class SmallVectorImpl;
 class Function;
 class DebugLoc;
+class OptBisect;
 
 /// This is an important class for using LLVM in a threaded context.  It
 /// (opaquely) owns and manages the core "global" data of LLVM's core
@@ -226,6 +227,9 @@ public:
     return OptionRegistry::instance().template get<ValT, Base, Mem>();
   }
 
+  /// \brief Access the object which manages optimization bisection for failure
+  /// analysis.
+  OptBisect &getOptBisect();
 private:
   LLVMContext(LLVMContext&) = delete;
   void operator=(LLVMContext&) = delete;

Added: llvm/trunk/include/llvm/IR/OptBisect.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/OptBisect.h?rev=267022&view=auto
==============================================================================
--- llvm/trunk/include/llvm/IR/OptBisect.h (added)
+++ llvm/trunk/include/llvm/IR/OptBisect.h Thu Apr 21 12:58:54 2016
@@ -0,0 +1,139 @@
+//===----------- llvm/IR/OptBisect.h - LLVM Bisect support -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file declares the interface for bisecting optimizations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_OPTBISECT_H
+#define LLVM_IR_OPTBISECT_H
+
+namespace llvm {
+
+class Pass;
+class StringRef;
+class Twine;
+
+/// This class implements a mechanism to disable passes and individual
+/// optimizations at compile time based on a command line option
+/// (-opt-bisect-limit) in order to perform a bisecting search for
+/// optimization-related problems.
+class OptBisect {
+public:
+  /// \brief Default constructor, initializes the OptBisect state based on the
+  /// -opt-bisect-limit command line argument.
+  ///
+  /// By default, bisection is disabled.
+  ///
+  /// Clients should not instantiate this class directly.  All access should go
+  /// through LLVMContext.
+  OptBisect();
+
+  /// Checks the bisect limit to determine if the specified pass should run.
+  ///
+  /// This function will immediate return true if bisection is disabled. If the
+  /// bisect limit is set to -1, the function will print a message describing
+  /// the pass and the bisect number assigned to it and return true.  Otherwise,
+  /// the function will print a message with the bisect number assigned to the
+  /// pass and indicating whether or not the pass will be run and return true if
+  /// the bisect limit has not yet been exceded or false if it has.
+  ///
+  /// Most passes should not call this routine directly.  Instead, it is called
+  /// through a helper routine provided by the pass base class.  For instance,
+  /// function passes should call FunctionPass::skipFunction().
+  template <class UnitT>
+  bool shouldRunPass(const Pass *P, const UnitT &U);
+
+  /// Checks the bisect limit to determine if the specified pass should run.
+  ///
+  /// This function will immediate return true if bisection is disabled. If the
+  /// bisect limit is set to -1, the function will print a message describing
+  /// the pass and the bisect number assigned to it and return true.  Otherwise,
+  /// the function will print a message with the bisect number assigned to the
+  /// pass and indicating whether or not the pass will be run and return true if
+  /// the bisect limit has not yet been exceded or false if it has.
+  ///
+  /// In order to avoid duplicating the code necessary to access OptBisect
+  /// through the LLVMContext class, passes may call one of the helper
+  /// functions that get the context from an IR object.  For instance,
+  /// function passes may call skipPassForFunction().
+  template <class UnitT>
+  bool shouldRunPass(const StringRef PassName, const UnitT &U);
+
+  /// Checks the bisect limit to determine if the optimization described by the
+  /// /p Desc argument should run.
+  ///
+  /// This function will immediate return true if bisection is disabled. If the
+  /// bisect limit is set to -1, the function will print a message with the
+  /// bisect number assigned to the optimization along with the /p Desc
+  /// description and return true.  Otherwise, the function will print a message
+  /// with the bisect number assigned to the optimization and indicating whether
+  /// or not the pass will be run and return true if the bisect limit has not
+  /// yet been exceded or false if it has.
+  ///
+  /// Passes may call this function to provide more fine grained control over
+  /// individual optimizations performed by the pass.  Passes which cannot be
+  /// skipped entirely (such as non-optional code generation passes) may still
+  /// call this function to control whether or not individual optional
+  /// transformations are performed.
+  bool shouldRunCase(const Twine &Desc);
+
+private:
+  bool checkPass(const StringRef PassName, const StringRef TargetDesc);
+
+  bool BisectEnabled = false;
+  unsigned LastBisectNum = 0;
+};
+
+// Access to OptBisect should go through LLVMContext, but for the
+// new pass manager there is no single base class from which a
+// helper function to abstract the messy details can be provided.
+// Instead, we provide standalone helper functions for each IR
+// type that must be handled.
+
+class Module;
+class Function;
+//class BasicBlock;
+//class Loop;
+
+/// Check with the OptBisect object to determine whether the described pass
+/// should be skipped.
+///
+/// This is a helper function which abstracts the details of accessing OptBisect
+/// through an LLVMContext obtained from a Module.
+bool skipPassForModule(const StringRef PassName, const Module &M);
+
+/// Check with the OptBisect object to determine whether the described pass
+/// should be skipped.
+///
+/// This is a helper function which abstracts the details of accessing OptBisect
+/// through an LLVMContext obtained from a Function.
+bool skipPassForFunction(const StringRef PassName, const Function &F);
+#if 0
+/// Check with the OptBisect object to determine whether the described pass
+/// should be skipped.
+///
+/// This is a helper function which abstracts the details of accessing OptBisect
+/// through an LLVMContext obtained from a BasicBlock.
+bool skipPassForBasicBlock(const StringRef PassName, const BasicBlock &BB);
+
+/// Check with the OptBisect object to determine whether the described pass
+/// should be skipped.
+///
+/// This is a helper function which abstracts the details of accessing OptBisect
+/// through an LLVMContext obtained from a Loop.
+bool skipPassForLoop(const StringRef PassName, const Loop &L);
+#endif
+// skiPassForSCC is declared in LazyCallGraph.h because of include file
+// dependency issues related to LazyCallGraph::SCC being nested.
+
+} // end namespace llvm
+
+#endif // LLVM_IR_OPTBISECT_H

Propchange: llvm/trunk/include/llvm/IR/OptBisect.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/include/llvm/IR/OptBisect.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: llvm/trunk/include/llvm/IR/OptBisect.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: llvm/trunk/include/llvm/Pass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Pass.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Pass.h (original)
+++ llvm/trunk/include/llvm/Pass.h Thu Apr 21 12:58:54 2016
@@ -251,6 +251,11 @@ public:
   explicit ModulePass(char &pid) : Pass(PT_Module, pid) {}
   // Force out-of-line virtual method.
   ~ModulePass() override;
+
+protected:
+  /// Optional passes call this function to check whether the pass should be
+  /// skipped. This is the case when optimization bisect is over the limit.
+  bool skipModule(Module &M) const;
 };
 
 
@@ -310,9 +315,10 @@ public:
   PassManagerType getPotentialPassManagerType() const override;
 
 protected:
-  /// skipOptnoneFunction - This function has Attribute::OptimizeNone
-  /// and most transformation passes should skip it.
-  bool skipOptnoneFunction(const Function &F) const;
+  /// Optional passes call this function to check whether the pass should be
+  /// skipped. This is the case when Attribute::OptimizeNone is set or when
+  /// optimization bisect is over the limit.
+  bool skipFunction(const Function &F) const;
 };
 
 
@@ -359,9 +365,10 @@ public:
   PassManagerType getPotentialPassManagerType() const override;
 
 protected:
-  /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone
-  /// and most transformation passes should skip it.
-  bool skipOptnoneFunction(const BasicBlock &BB) const;
+  /// Optional passes call this function to check whether the pass should be
+  /// skipped. This is the case when Attribute::OptimizeNone is set or when
+  /// optimization bisect is over the limit.
+  bool skipBasicBlock(const BasicBlock &BB) const;
 };
 
 /// If the user specifies the -time-passes argument on an LLVM tool command line

Modified: llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp (original)
+++ llvm/trunk/lib/Analysis/CallGraphSCCPass.cpp Thu Apr 21 12:58:54 2016
@@ -23,6 +23,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/LegacyPassManagers.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Timer.h"
@@ -444,7 +445,7 @@ bool CGPassManager::runOnModule(Module &
   // Walk the callgraph in bottom-up SCC order.
   scc_iterator<CallGraph*> CGI = scc_begin(&CG);
 
-  CallGraphSCC CurSCC(&CGI);
+  CallGraphSCC CurSCC(CG, &CGI);
   while (!CGI.isAtEnd()) {
     // Copy the current SCC and increment past it so that the pass can hack
     // on the SCC if it wants to without invalidating our iterator.
@@ -631,3 +632,9 @@ Pass *CallGraphSCCPass::createPrinterPas
   return new PrintCallGraphPass(Banner, O);
 }
 
+bool CallGraphSCCPass::skipSCC(CallGraphSCC &SCC) const {
+  return !SCC.getCallGraph().getModule()
+              .getContext()
+              .getOptBisect()
+              .shouldRunPass(this, SCC);
+}

Modified: llvm/trunk/lib/Analysis/LoopPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopPass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LoopPass.cpp (original)
+++ llvm/trunk/lib/Analysis/LoopPass.cpp Thu Apr 21 12:58:54 2016
@@ -16,6 +16,7 @@
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Timer.h"
@@ -335,11 +336,16 @@ void LoopPass::assignPassManager(PMStack
   LPPM->add(this);
 }
 
-// Containing function has Attribute::OptimizeNone and transformation
-// passes should skip it.
-bool LoopPass::skipOptnoneFunction(const Loop *L) const {
+bool LoopPass::skipLoop(const Loop *L) const {
   const Function *F = L->getHeader()->getParent();
-  if (F && F->hasFnAttribute(Attribute::OptimizeNone)) {
+  if (!F)
+    return false;
+  // Check the opt bisect limit.
+  LLVMContext &Context = F->getContext();
+  if (!Context.getOptBisect().shouldRunPass(this, *L))
+    return true;
+  // Check for the OptimizeNone attribute.
+  if (F->hasFnAttribute(Attribute::OptimizeNone)) {
     // FIXME: Report this to dbgs() only once per function.
     DEBUG(dbgs() << "Skipping pass '" << getPassName()
           << "' in function " << F->getName() << "\n");

Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/BranchFolding.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/BranchFolding.cpp (original)
+++ llvm/trunk/lib/CodeGen/BranchFolding.cpp Thu Apr 21 12:58:54 2016
@@ -90,7 +90,7 @@ INITIALIZE_PASS(BranchFolderPass, "branc
                 "Control Flow Optimizer", false, false)
 
 bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();

Modified: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp Thu Apr 21 12:58:54 2016
@@ -211,7 +211,7 @@ FunctionPass *llvm::createCodeGenPrepare
 }
 
 bool CodeGenPrepare::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   DL = &F.getParent()->getDataLayout();

Modified: llvm/trunk/lib/CodeGen/DeadMachineInstructionElim.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DeadMachineInstructionElim.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/DeadMachineInstructionElim.cpp (original)
+++ llvm/trunk/lib/CodeGen/DeadMachineInstructionElim.cpp Thu Apr 21 12:58:54 2016
@@ -90,7 +90,7 @@ bool DeadMachineInstructionElim::isDead(
 }
 
 bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   bool AnyChanges = false;

Modified: llvm/trunk/lib/CodeGen/LowerEmuTLS.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LowerEmuTLS.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LowerEmuTLS.cpp (original)
+++ llvm/trunk/lib/CodeGen/LowerEmuTLS.cpp Thu Apr 21 12:58:54 2016
@@ -63,6 +63,9 @@ ModulePass *llvm::createLowerEmuTLSPass(
 }
 
 bool LowerEmuTLS::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   if (!TM || !TM->Options.EmulatedTLS)
     return false;
 

Modified: llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineBlockPlacement.cpp Thu Apr 21 12:58:54 2016
@@ -1430,7 +1430,7 @@ bool MachineBlockPlacement::runOnMachine
   if (std::next(F.begin()) == F.end())
     return false;
 
-  if (skipOptnoneFunction(*F.getFunction()))
+  if (skipFunction(*F.getFunction()))
     return false;
 
   MBPI = &getAnalysis<MachineBranchProbabilityInfo>();

Modified: llvm/trunk/lib/CodeGen/MachineCSE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCSE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineCSE.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineCSE.cpp Thu Apr 21 12:58:54 2016
@@ -704,7 +704,7 @@ bool MachineCSE::PerformCSE(MachineDomTr
 }
 
 bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   TII = MF.getSubtarget().getInstrInfo();

Modified: llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineCopyPropagation.cpp Thu Apr 21 12:58:54 2016
@@ -349,7 +349,7 @@ void MachineCopyPropagation::CopyPropaga
 }
 
 bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   Changed = false;

Modified: llvm/trunk/lib/CodeGen/MachineLICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineLICM.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineLICM.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineLICM.cpp Thu Apr 21 12:58:54 2016
@@ -260,7 +260,7 @@ static bool LoopIsOuterMostWithPredecess
 }
 
 bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   Changed = FirstInLoop = false;

Modified: llvm/trunk/lib/CodeGen/MachineScheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineScheduler.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineScheduler.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineScheduler.cpp Thu Apr 21 12:58:54 2016
@@ -319,7 +319,7 @@ ScheduleDAGInstrs *PostMachineScheduler:
 /// design would be to split blocks at scheduling boundaries, but LLVM has a
 /// general bias against block splitting purely for implementation simplicity.
 bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
-  if (skipOptnoneFunction(*mf.getFunction()))
+  if (skipFunction(*mf.getFunction()))
     return false;
 
   if (EnableMachineSched.getNumOccurrences()) {
@@ -357,7 +357,7 @@ bool MachineScheduler::runOnMachineFunct
 }
 
 bool PostMachineScheduler::runOnMachineFunction(MachineFunction &mf) {
-  if (skipOptnoneFunction(*mf.getFunction()))
+  if (skipFunction(*mf.getFunction()))
     return false;
 
   if (EnablePostRAMachineSched.getNumOccurrences()) {

Modified: llvm/trunk/lib/CodeGen/MachineSink.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineSink.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineSink.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineSink.cpp Thu Apr 21 12:58:54 2016
@@ -257,7 +257,7 @@ MachineSinking::AllUsesDominatedByBlock(
 }
 
 bool MachineSinking::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   DEBUG(dbgs() << "******** Machine Sinking ********\n");

Modified: llvm/trunk/lib/CodeGen/OptimizePHIs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/OptimizePHIs.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/OptimizePHIs.cpp (original)
+++ llvm/trunk/lib/CodeGen/OptimizePHIs.cpp Thu Apr 21 12:58:54 2016
@@ -63,7 +63,7 @@ INITIALIZE_PASS(OptimizePHIs, "opt-phis"
                 "Optimize machine instruction PHIs", false, false)
 
 bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
-  if (skipOptnoneFunction(*Fn.getFunction()))
+  if (skipFunction(*Fn.getFunction()))
     return false;
 
   MRI = &Fn.getRegInfo();

Modified: llvm/trunk/lib/CodeGen/PeepholeOptimizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PeepholeOptimizer.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PeepholeOptimizer.cpp (original)
+++ llvm/trunk/lib/CodeGen/PeepholeOptimizer.cpp Thu Apr 21 12:58:54 2016
@@ -1471,7 +1471,7 @@ bool PeepholeOptimizer::foldRedundantNAP
 }
 
 bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   DEBUG(dbgs() << "********** PEEPHOLE OPTIMIZER **********\n");

Modified: llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp (original)
+++ llvm/trunk/lib/CodeGen/PostRASchedulerList.cpp Thu Apr 21 12:58:54 2016
@@ -273,7 +273,7 @@ bool PostRAScheduler::enablePostRASchedu
 }
 
 bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
-  if (skipOptnoneFunction(*Fn.getFunction()))
+  if (skipFunction(*Fn.getFunction()))
     return false;
 
   TII = Fn.getSubtarget().getInstrInfo();

Modified: llvm/trunk/lib/CodeGen/StackColoring.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackColoring.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/StackColoring.cpp (original)
+++ llvm/trunk/lib/CodeGen/StackColoring.cpp Thu Apr 21 12:58:54 2016
@@ -657,7 +657,7 @@ void StackColoring::expungeSlotMap(Dense
 }
 
 bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
-  if (skipOptnoneFunction(*Func.getFunction()))
+  if (skipFunction(*Func.getFunction()))
     return false;
 
   DEBUG(dbgs() << "********** Stack Coloring **********\n"

Modified: llvm/trunk/lib/CodeGen/TailDuplication.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TailDuplication.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TailDuplication.cpp (original)
+++ llvm/trunk/lib/CodeGen/TailDuplication.cpp Thu Apr 21 12:58:54 2016
@@ -44,7 +44,7 @@ INITIALIZE_PASS(TailDuplicatePass, "tail
                 false)
 
 bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) {
-  if (skipOptnoneFunction(*MF.getFunction()))
+  if (skipFunction(*MF.getFunction()))
     return false;
 
   auto MMI = getAnalysisIfAvailable<MachineModuleInfo>();

Modified: llvm/trunk/lib/IR/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/CMakeLists.txt?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/IR/CMakeLists.txt (original)
+++ llvm/trunk/lib/IR/CMakeLists.txt Thu Apr 21 12:58:54 2016
@@ -39,6 +39,7 @@ add_llvm_library(LLVMCore
   Module.cpp
   ModuleSummaryIndex.cpp
   Operator.cpp
+  OptBisect.cpp
   Pass.cpp
   PassManager.cpp
   PassRegistry.cpp

Modified: llvm/trunk/lib/IR/LLVMContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContext.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContext.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContext.cpp Thu Apr 21 12:58:54 2016
@@ -325,3 +325,7 @@ void LLVMContext::disableDebugTypeODRUni
 void LLVMContext::setDiscardValueNames(bool Discard) {
   pImpl->DiscardValueNames = Discard;
 }
+
+OptBisect &LLVMContext::getOptBisect() {
+  return pImpl->getOptBisect();
+}

Modified: llvm/trunk/lib/IR/LLVMContextImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.cpp (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.cpp Thu Apr 21 12:58:54 2016
@@ -16,6 +16,8 @@
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
+#include "llvm/Support/ManagedStatic.h"
 #include <algorithm>
 using namespace llvm;
 
@@ -232,3 +234,19 @@ void GetElementPtrConstantExpr::anchor()
 
 void CompareConstantExpr::anchor() { }
 
+/// Singleton instance of the OptBisect class.
+///
+/// This singleton is accessed via the LLVMContext::getOptBisect() function.  It
+/// provides a mechanism to disable passes and individual optimizations at
+/// compile time based on a command line option (-opt-bisect-limit) in order to
+/// perform a bisecting search for optimization-related problems.
+///
+/// Even if multiple LLVMContext objects are created, they will all return the
+/// same instance of OptBisect in order to provide a single bisect count.  Any
+/// code that uses the OptBisect object should be serialized when bisection is
+/// enabled in order to enable a consistent bisect count.
+static ManagedStatic<OptBisect> OptBisector;
+
+OptBisect &LLVMContextImpl::getOptBisect() {
+  return *OptBisector;
+}

Modified: llvm/trunk/lib/IR/LLVMContextImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Thu Apr 21 12:58:54 2016
@@ -1133,6 +1133,10 @@ public:
 
   /// Destroy the ConstantArrays if they are not used.
   void dropTriviallyDeadConstantArrays();
+
+  /// \brief Access the object which manages optimization bisection for failure
+  /// analysis.
+  OptBisect &getOptBisect();
 };
 
 }

Added: llvm/trunk/lib/IR/OptBisect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/OptBisect.cpp?rev=267022&view=auto
==============================================================================
--- llvm/trunk/lib/IR/OptBisect.cpp (added)
+++ llvm/trunk/lib/IR/OptBisect.cpp Thu Apr 21 12:58:54 2016
@@ -0,0 +1,176 @@
+//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements support for a bisecting optimizations based on a
+/// command line option.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden,
+                                   cl::init(INT_MAX), cl::Optional,
+                                   cl::desc("Maximum optimization to perform"));
+
+OptBisect::OptBisect() {
+  BisectEnabled = OptBisectLimit != INT_MAX;
+}
+
+static void printPassMessage(const StringRef &Name, int PassNum,
+                             StringRef TargetDesc, bool Running) {
+  StringRef Status = Running ? "" : "NOT ";
+  errs() << "BISECT: " << Status << "running pass "
+         << "(" << PassNum << ") " << Name << " on " << TargetDesc << "\n";
+}
+
+static void printCaseMessage(int CaseNum, StringRef Msg, bool Running) {
+  if (Running)
+    errs() << "BISECT: running case (";
+  else
+    errs() << "BISECT: NOT running case (";
+  errs() << CaseNum << "): " << Msg << "\n";
+}
+
+static std::string getDescription(const Module &M) {
+  return "module (" + M.getName().str() + ")";
+}
+
+static std::string getDescription(const Function &F) {
+  return "function (" + F.getName().str() + ")";
+}
+
+static std::string getDescription(const BasicBlock &BB) {
+  return "basic block (" + BB.getName().str() + ") in function (" +
+         BB.getParent()->getName().str() + ")";
+}
+
+static std::string getDescription(const Loop &L) {
+  // FIXME: I'd like to be able to provide a better description here, but
+  //        calling L->getHeader() would introduce a new dependency on the
+  //        LLVMCore library.
+  return "loop";
+}
+
+static std::string getDescription(const CallGraphSCC &SCC) {
+  std::string Desc = "SCC (";
+  bool First = true;
+  for (CallGraphNode *CGN : SCC) {
+    if (First)
+      First = false;
+    else
+      Desc += ", ";
+    Function *F = CGN->getFunction();
+    if (F)
+      Desc += F->getName();
+    else
+      Desc += "<<null function>>";
+  }
+  Desc += ")";
+  return Desc;
+}
+
+static std::string getDescription(const LazyCallGraph::SCC &SCC) {
+  std::string Desc = "SCC (";
+  bool First = true;
+  for (LazyCallGraph::Node &CGN : SCC) {
+    if (First)
+      First = false;
+    else
+      Desc += ", ";
+    Function &F = CGN.getFunction();
+    Desc += F.getName();
+  }
+  Desc += ")";
+  return Desc;
+}
+
+// Force instantiations.
+template bool OptBisect::shouldRunPass(const Pass *, const Module &);
+template bool OptBisect::shouldRunPass(const Pass *, const Function &);
+template bool OptBisect::shouldRunPass(const Pass *, const BasicBlock &);
+template bool OptBisect::shouldRunPass(const Pass *, const Loop &);
+template bool OptBisect::shouldRunPass(const Pass *, const CallGraphSCC &);
+template bool OptBisect::shouldRunPass(const StringRef PassName,
+                                       const Module &);
+template bool OptBisect::shouldRunPass(const StringRef PassName,
+                                       const Function &);
+template bool OptBisect::shouldRunPass(const StringRef PassName,
+                                       const BasicBlock &);
+template bool OptBisect::shouldRunPass(const StringRef PassName, const Loop &);
+template bool OptBisect::shouldRunPass(const StringRef PassName,
+                                       const LazyCallGraph::SCC &);
+
+template <class UnitT>
+bool OptBisect::shouldRunPass(const Pass *P, const UnitT &U) {
+  if (!BisectEnabled)
+    return true;
+  return checkPass(P->getPassName(), getDescription(U));
+}
+
+// Interface function for the new pass manager.
+template <class UnitT>
+bool OptBisect::shouldRunPass(const StringRef PassName, const UnitT &U) {
+  if (!BisectEnabled)
+    return true;
+  return checkPass(PassName, getDescription(U));
+}
+
+bool OptBisect::checkPass(const StringRef PassName,
+                          const StringRef TargetDesc) {
+  assert(BisectEnabled);
+
+  int CurBisectNum = ++LastBisectNum;
+  bool ShouldRun = (OptBisectLimit == -1 || CurBisectNum <= OptBisectLimit);
+  printPassMessage(PassName, CurBisectNum, TargetDesc, ShouldRun);
+  return ShouldRun;
+}
+
+bool OptBisect::shouldRunCase(const Twine &Msg) {
+  if (!BisectEnabled)
+    return true;
+  int CurFuelNum = ++LastBisectNum;
+  bool ShouldRun = (OptBisectLimit == -1 || CurFuelNum <= OptBisectLimit);
+  printCaseMessage(CurFuelNum, Msg.str(), ShouldRun);
+  return ShouldRun;
+}
+
+bool llvm::skipPassForModule(const StringRef PassName, const Module &M) {
+  return !M.getContext().getOptBisect().shouldRunPass(PassName, M);
+}
+
+bool llvm::skipPassForFunction(const StringRef PassName, const Function &F) {
+  return !F.getContext().getOptBisect().shouldRunPass(PassName, F);
+}
+#if 0
+bool llvm::skipPassForBasicBlock(const StringRef PassName, const BasicBlock &BB) {
+  return !BB.getContext().getOptBisect().shouldRunPass(PassName, BB);
+}
+
+bool llvm::skipPassForLoop(const StringRef PassName, const Loop &L) {
+  const Function *F = L.getHeader()->getParent();
+  if (!F)
+    return false;
+  return !F->getContext().getOptBisect().shouldRunPass(PassName, L);
+}
+#endif
+bool llvm::skipPassForSCC(const StringRef PassName, const LazyCallGraph::SCC &SCC) {
+  LLVMContext &Context = SCC.begin()->getFunction().getContext();
+  return !Context.getOptBisect().shouldRunPass(PassName, SCC);
+}
+

Propchange: llvm/trunk/lib/IR/OptBisect.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/lib/IR/OptBisect.cpp
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: llvm/trunk/lib/IR/OptBisect.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: llvm/trunk/lib/IR/Pass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Pass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Pass.cpp (original)
+++ llvm/trunk/lib/IR/Pass.cpp Thu Apr 21 12:58:54 2016
@@ -17,6 +17,8 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LegacyPassNameParser.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/PassRegistry.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -45,6 +47,10 @@ PassManagerType ModulePass::getPotential
   return PMT_ModulePassManager;
 }
 
+bool ModulePass::skipModule(Module &M) const {
+  return !M.getContext().getOptBisect().shouldRunPass(this, M);
+}
+
 bool Pass::mustPreserveAnalysisID(char &AID) const {
   return Resolver->getAnalysisIfAvailable(&AID, true) != nullptr;
 }
@@ -140,10 +146,13 @@ PassManagerType FunctionPass::getPotenti
   return PMT_FunctionPassManager;
 }
 
-bool FunctionPass::skipOptnoneFunction(const Function &F) const {
+bool FunctionPass::skipFunction(const Function &F) const {
+  if (!F.getContext().getOptBisect().shouldRunPass(this, F))
+    return true;
+
   if (F.hasFnAttribute(Attribute::OptimizeNone)) {
-    DEBUG(dbgs() << "Skipping pass '" << getPassName()
-          << "' on function " << F.getName() << "\n");
+    DEBUG(dbgs() << "Skipping pass '" << getPassName() << "' on function "
+                 << F.getName() << "\n");
     return true;
   }
   return false;
@@ -168,9 +177,13 @@ bool BasicBlockPass::doFinalization(Func
   return false;
 }
 
-bool BasicBlockPass::skipOptnoneFunction(const BasicBlock &BB) const {
+bool BasicBlockPass::skipBasicBlock(const BasicBlock &BB) const {
   const Function *F = BB.getParent();
-  if (F && F->hasFnAttribute(Attribute::OptimizeNone)) {
+  if (!F)
+    return false;
+  if (!F->getContext().getOptBisect().shouldRunPass(this, BB))
+    return true;
+  if (F->hasFnAttribute(Attribute::OptimizeNone)) {
     // Report this only once per function.
     if (&BB == &F->getEntryBlock())
       DEBUG(dbgs() << "Skipping pass '" << getPassName()

Modified: llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp Thu Apr 21 12:58:54 2016
@@ -114,6 +114,9 @@ Pass *llvm::createArgumentPromotionPass(
 }
 
 bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) {
+  if (skipSCC(SCC))
+    return false;
+
   bool Changed = false, LocalChange;
 
   do {  // Iterate until we stop promoting from this SCC.

Modified: llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp Thu Apr 21 12:58:54 2016
@@ -96,6 +96,8 @@ unsigned ConstantMerge::getAlignment(Glo
 }
 
 bool ConstantMerge::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
 
   // Find all the globals that are marked "used".  These cannot be merged.
   SmallPtrSet<const GlobalValue*, 8> UsedGlobals;

Modified: llvm/trunk/lib/Transforms/IPO/CrossDSOCFI.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/CrossDSOCFI.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/CrossDSOCFI.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/CrossDSOCFI.cpp Thu Apr 21 12:58:54 2016
@@ -158,6 +158,9 @@ void CrossDSOCFI::buildCFICheck() {
 }
 
 bool CrossDSOCFI::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   if (M.getModuleFlag("Cross-DSO CFI") == nullptr)
     return false;
   buildCFICheck();

Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Thu Apr 21 12:58:54 2016
@@ -1092,6 +1092,9 @@ bool DAE::RemoveDeadStuffFromFunction(Fu
 }
 
 bool DAE::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   // First pass: Do a simple check to see if any functions can have their "..."

Modified: llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ElimAvailExtern.cpp Thu Apr 21 12:58:54 2016
@@ -50,6 +50,9 @@ ModulePass *llvm::createEliminateAvailab
 }
 
 bool EliminateAvailableExternally::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   // Drop initializers of available externally global variables.

Modified: llvm/trunk/lib/Transforms/IPO/ExtractGV.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/ExtractGV.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/ExtractGV.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/ExtractGV.cpp Thu Apr 21 12:58:54 2016
@@ -68,6 +68,9 @@ namespace {
       : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {}
 
     bool runOnModule(Module &M) override {
+      if (skipModule(M))
+        return false;
+
       // Visit the global inline asm.
       if (!deleteStuff)
         M.setModuleInlineAsm("");

Modified: llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionAttrs.cpp Thu Apr 21 12:58:54 2016
@@ -987,6 +987,9 @@ static bool addNoRecurseAttrs(const SCCN
 
 PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
                                                   CGSCCAnalysisManager &AM) {
+  if (skipPassForSCC(name(), C))
+    return PreservedAnalyses::all();
+
   Module &M = *C.begin()->getFunction().getParent();
   const ModuleAnalysisManager &MAM =
       AM.getResult<ModuleAnalysisManagerCGSCCProxy>(C).getManager();
@@ -1081,6 +1084,9 @@ INITIALIZE_PASS_END(PostOrderFunctionAtt
 Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); }
 
 bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
+  if (skipSCC(SCC))
+    return false;
+
   TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
   bool Changed = false;
 
@@ -1195,6 +1201,9 @@ static bool addNoRecurseAttrsTopDown(Fun
 }
 
 bool ReversePostOrderFunctionAttrs::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   // We only have a post-order SCC traversal (because SCCs are inherently
   // discovered in post-order), so we accumulate them in a vector and then walk
   // it in reverse. This is simpler than using the RPO iterator infrastructure

Modified: llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/FunctionImport.cpp Thu Apr 21 12:58:54 2016
@@ -499,6 +499,9 @@ public:
       : ModulePass(ID), Index(Index) {}
 
   bool runOnModule(Module &M) override {
+    if (skipModule(M))
+      return false;
+
     if (SummaryFile.empty() && !Index)
       report_fatal_error("error: -function-import requires -summary-file or "
                          "file from frontend\n");

Modified: llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalDCE.cpp Thu Apr 21 12:58:54 2016
@@ -75,6 +75,9 @@ INITIALIZE_PASS(GlobalDCE, "globaldce",
 ModulePass *llvm::createGlobalDCEPass() { return new GlobalDCE(); }
 
 bool GlobalDCE::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   // Remove empty functions from the global ctors list.

Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Thu Apr 21 12:58:54 2016
@@ -2528,6 +2528,9 @@ bool GlobalOpt::OptimizeEmptyGlobalCXXDt
 }
 
 bool GlobalOpt::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   auto &DL = M.getDataLayout();

Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Thu Apr 21 12:58:54 2016
@@ -54,6 +54,9 @@ INITIALIZE_PASS(IPCP, "ipconstprop",
 ModulePass *llvm::createIPConstantPropagationPass() { return new IPCP(); }
 
 bool IPCP::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
   bool LocalChange = true;
 

Modified: llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/InferFunctionAttrs.cpp Thu Apr 21 12:58:54 2016
@@ -14,6 +14,7 @@
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
@@ -955,6 +956,9 @@ static bool inferAllPrototypeAttributes(
 
 PreservedAnalyses InferFunctionAttrsPass::run(Module &M,
                                               AnalysisManager<Module> &AM) {
+  if (skipPassForModule(name(), M))
+    return PreservedAnalyses::all();
+
   auto &TLI = AM.getResult<TargetLibraryAnalysis>(M);
 
   if (!inferAllPrototypeAttributes(M, TLI))
@@ -979,6 +983,9 @@ struct InferFunctionAttrsLegacyPass : pu
   }
 
   bool runOnModule(Module &M) override {
+    if (skipModule(M))
+      return false;
+
     auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
     return inferAllPrototypeAttributes(M, TLI);
   }

Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Thu Apr 21 12:58:54 2016
@@ -356,6 +356,9 @@ static bool InlineHistoryIncludes(Functi
 }
 
 bool Inliner::runOnSCC(CallGraphSCC &SCC) {
+  if (skipSCC(SCC))
+    return false;
+
   CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
   ACT = &getAnalysis<AssumptionCacheTracker>();
   auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();

Modified: llvm/trunk/lib/Transforms/IPO/Internalize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Internalize.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/Internalize.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/Internalize.cpp Thu Apr 21 12:58:54 2016
@@ -105,6 +105,9 @@ public:
   }
 
   bool runOnModule(Module &M) override {
+    if (skipModule(M))
+      return false;
+
     CallGraphWrapperPass *CGPass =
         getAnalysisIfAvailable<CallGraphWrapperPass>();
     CallGraph *CG = CGPass ? &CGPass->getCallGraph() : nullptr;

Modified: llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LoopExtractor.cpp Thu Apr 21 12:58:54 2016
@@ -81,7 +81,7 @@ INITIALIZE_PASS(SingleLoopExtractor, "lo
 Pass *llvm::createLoopExtractorPass() { return new LoopExtractor(); }
 
 bool LoopExtractor::runOnLoop(Loop *L, LPPassManager &) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   // Only visit top-level loops.
@@ -249,6 +249,9 @@ void BlockExtractorPass::SplitLandingPad
 }
 
 bool BlockExtractorPass::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   std::set<BasicBlock*> TranslatedBlocksToNotExtract;
   for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
     BasicBlock *BB = BlocksToNotExtract[i];

Modified: llvm/trunk/lib/Transforms/IPO/LowerBitSets.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerBitSets.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/LowerBitSets.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/LowerBitSets.cpp Thu Apr 21 12:58:54 2016
@@ -1051,6 +1051,9 @@ bool LowerBitSets::eraseBitSetMetadata()
 }
 
 bool LowerBitSets::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = buildBitSets();
   Changed |= eraseBitSetMetadata();
   return Changed;

Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Thu Apr 21 12:58:54 2016
@@ -1525,6 +1525,9 @@ bool MergeFunctions::doSanityCheck(std::
 }
 
 bool MergeFunctions::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   // All functions in the module, ordered by hash. Functions with a unique

Modified: llvm/trunk/lib/Transforms/IPO/PartialInlining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PartialInlining.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/PartialInlining.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/PartialInlining.cpp Thu Apr 21 12:58:54 2016
@@ -149,6 +149,9 @@ Function* PartialInliner::unswitchFuncti
 }
 
 bool PartialInliner::runOnModule(Module& M) {
+  if (skipModule(M))
+    return false;
+
   std::vector<Function*> worklist;
   worklist.reserve(M.size());
   for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)

Modified: llvm/trunk/lib/Transforms/IPO/PruneEH.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PruneEH.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/PruneEH.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/PruneEH.cpp Thu Apr 21 12:58:54 2016
@@ -63,6 +63,9 @@ Pass *llvm::createPruneEHPass() { return
 
 
 bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
+  if (skipSCC(SCC))
+    return false;
+
   SmallPtrSet<CallGraphNode *, 8> SCCNodes;
   CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
   bool MadeChange = false;

Modified: llvm/trunk/lib/Transforms/IPO/StripDeadPrototypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/StripDeadPrototypes.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/StripDeadPrototypes.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/StripDeadPrototypes.cpp Thu Apr 21 12:58:54 2016
@@ -17,6 +17,7 @@
 #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Pass.h"
 #include "llvm/Transforms/IPO.h"
 
@@ -54,6 +55,9 @@ static bool stripDeadPrototypes(Module &
 }
 
 PreservedAnalyses StripDeadPrototypesPass::run(Module &M) {
+  if (skipPassForModule(name(), M))
+    return PreservedAnalyses::all();
+
   if (stripDeadPrototypes(M))
     return PreservedAnalyses::none();
   return PreservedAnalyses::all();
@@ -69,6 +73,9 @@ public:
         *PassRegistry::getPassRegistry());
   }
   bool runOnModule(Module &M) override {
+    if (skipModule(M))
+      return false;
+
     return stripDeadPrototypes(M);
   }
 };

Modified: llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp Thu Apr 21 12:58:54 2016
@@ -229,6 +229,9 @@ static bool StripSymbolNames(Module &M,
 }
 
 bool StripSymbols::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
   Changed |= StripDebugInfo(M);
   if (!OnlyDebugInfo)
@@ -237,10 +240,15 @@ bool StripSymbols::runOnModule(Module &M
 }
 
 bool StripNonDebugSymbols::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   return StripSymbolNames(M, true);
 }
 
 bool StripDebugDeclare::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
 
   Function *Declare = M.getFunction("llvm.dbg.declare");
   std::vector<Constant*> DeadConstants;
@@ -286,6 +294,9 @@ bool StripDebugDeclare::runOnModule(Modu
 /// optimized away by the optimizer. This special pass removes debug info for
 /// such symbols.
 bool StripDeadDebugInfo::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   bool Changed = false;
 
   LLVMContext &C = M.getContext();

Modified: llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp Thu Apr 21 12:58:54 2016
@@ -265,7 +265,12 @@ struct WholeProgramDevirt : public Modul
   WholeProgramDevirt() : ModulePass(ID) {
     initializeWholeProgramDevirtPass(*PassRegistry::getPassRegistry());
   }
-  bool runOnModule(Module &M) { return DevirtModule(M).run(); }
+  bool runOnModule(Module &M) {
+    if (skipModule(M))
+      return false;
+
+    return DevirtModule(M).run();
+  }
 };
 
 } // anonymous namespace

Modified: llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp Thu Apr 21 12:58:54 2016
@@ -56,6 +56,7 @@
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/GetElementPtrTypeIterator.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/ValueHandle.h"
 #include "llvm/Support/CommandLine.h"
@@ -3088,6 +3089,9 @@ combineInstructionsOverFunction(Function
 
 PreservedAnalyses InstCombinePass::run(Function &F,
                                        AnalysisManager<Function> &AM) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   auto &AC = AM.getResult<AssumptionAnalysis>(F);
   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
@@ -3120,7 +3124,7 @@ void InstructionCombiningPass::getAnalys
 }
 
 bool InstructionCombiningPass::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   // Required analyses.

Modified: llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp Thu Apr 21 12:58:54 2016
@@ -778,6 +778,9 @@ static void createIRLevelProfileFlagVari
 }
 
 bool PGOInstrumentationGen::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   createIRLevelProfileFlagVariable(M);
   for (auto &F : M) {
     if (F.isDeclaration())
@@ -801,6 +804,9 @@ static void setPGOCountOnFunc(PGOUseFunc
 }
 
 bool PGOInstrumentationUse::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   DEBUG(dbgs() << "Read in profile counters: ");
   auto &Ctx = M.getContext();
   // Read the counter array from file.

Modified: llvm/trunk/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp (original)
+++ llvm/trunk/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp Thu Apr 21 12:58:54 2016
@@ -132,6 +132,9 @@ bool ObjCARCAPElim::runOnModule(Module &
   if (!ModuleHasARC(M))
     return false;
 
+  if (skipModule(M))
+    return false;
+
   // Find the llvm.global_ctors variable, as the first step in
   // identifying the global constructors. In theory, unnecessary autorelease
   // pools could occur anywhere, but in practice it's pretty rare. Global

Modified: llvm/trunk/lib/Transforms/Scalar/ADCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ADCE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ADCE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/ADCE.cpp Thu Apr 21 12:58:54 2016
@@ -26,6 +26,7 @@
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Pass.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Transforms/Scalar.h"
@@ -146,6 +147,9 @@ static bool aggressiveDCE(Function& F) {
 }
 
 PreservedAnalyses ADCEPass::run(Function &F) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   if (aggressiveDCE(F))
     return PreservedAnalyses::none();
   return PreservedAnalyses::all();
@@ -159,7 +163,7 @@ struct ADCELegacyPass : public FunctionP
   }
 
   bool runOnFunction(Function& F) override {
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
     return aggressiveDCE(F);
   }

Modified: llvm/trunk/lib/Transforms/Scalar/BDCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/BDCE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/BDCE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/BDCE.cpp Thu Apr 21 12:58:54 2016
@@ -59,7 +59,7 @@ INITIALIZE_PASS_END(BDCE, "bdce", "Bit-T
                     false, false)
 
 bool BDCE::runOnFunction(Function& F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
   auto &DB = getAnalysis<DemandedBitsWrapperPass>().getDemandedBits();
 

Modified: llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/ConstantHoisting.cpp Thu Apr 21 12:58:54 2016
@@ -187,7 +187,7 @@ FunctionPass *llvm::createConstantHoisti
 
 /// \brief Perform the constant hoisting optimization for the given function.
 bool ConstantHoisting::runOnFunction(Function &Fn) {
-  if (skipOptnoneFunction(Fn))
+  if (skipFunction(Fn))
     return false;
 
   DEBUG(dbgs() << "********** Begin Constant Hoisting **********\n");

Modified: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp Thu Apr 21 12:58:54 2016
@@ -399,7 +399,7 @@ Constant *CorrelatedValuePropagation::ge
 }
 
 bool CorrelatedValuePropagation::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   LVI = &getAnalysis<LazyValueInfo>();

Modified: llvm/trunk/lib/Transforms/Scalar/DCE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DCE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/DCE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/DCE.cpp Thu Apr 21 12:58:54 2016
@@ -41,7 +41,7 @@ namespace {
       initializeDeadInstEliminationPass(*PassRegistry::getPassRegistry());
     }
     bool runOnBasicBlock(BasicBlock &BB) override {
-      if (skipOptnoneFunction(BB))
+      if (skipBasicBlock(BB))
         return false;
       auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
       TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI() : nullptr;
@@ -122,7 +122,7 @@ static bool DCEInstruction(Instruction *
 }
 
 bool DCE::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();

Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Thu Apr 21 12:58:54 2016
@@ -58,7 +58,7 @@ namespace {
     }
 
     bool runOnFunction(Function &F) override {
-      if (skipOptnoneFunction(F))
+      if (skipFunction(F))
         return false;
 
       AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();

Modified: llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/EarlyCSE.cpp Thu Apr 21 12:58:54 2016
@@ -25,6 +25,7 @@
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/Debug.h"
@@ -819,6 +820,9 @@ bool EarlyCSE::run() {
 
 PreservedAnalyses EarlyCSEPass::run(Function &F,
                                     AnalysisManager<Function> &AM) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
@@ -853,7 +857,7 @@ public:
   }
 
   bool runOnFunction(Function &F) override {
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
 
     auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();

Modified: llvm/trunk/lib/Transforms/Scalar/Float2Int.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Float2Int.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Float2Int.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Float2Int.cpp Thu Apr 21 12:58:54 2016
@@ -516,7 +516,7 @@ void Float2Int::cleanup() {
 }
 
 bool Float2Int::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   DEBUG(dbgs() << "F2I: Looking at function " << F.getName() << "\n");

Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Apr 21 12:58:54 2016
@@ -43,6 +43,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -584,6 +585,9 @@ void GVN::ValueTable::verifyRemoved(cons
 //===----------------------------------------------------------------------===//
 
 PreservedAnalyses GVN::run(Function &F, AnalysisManager<Function> &AM) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   // FIXME: The order of evaluation of these 'getResult' calls is very
   // significant! Re-ordering these variables will cause GVN when run alone to
   // be less effective! We should fix memdep and basic-aa to not exhibit this
@@ -2675,7 +2679,7 @@ public:
   }
 
   bool runOnFunction(Function &F) override {
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
 
     return Impl.runImpl(

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Thu Apr 21 12:58:54 2016
@@ -2122,7 +2122,7 @@ void IndVarSimplify::sinkUnusedInvariant
 //===----------------------------------------------------------------------===//
 
 bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   // If LoopSimplify form is not available, stay out of trouble. Some notes:

Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Thu Apr 21 12:58:54 2016
@@ -187,7 +187,7 @@ FunctionPass *llvm::createJumpThreadingP
 /// runOnFunction - Top level algorithm.
 ///
 bool JumpThreading::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n");

Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Thu Apr 21 12:58:54 2016
@@ -174,7 +174,7 @@ Pass *llvm::createLICMPass() { return ne
 /// times on one loop.
 ///
 bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   Changed = false;

Modified: llvm/trunk/lib/Transforms/Scalar/LoadCombine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoadCombine.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoadCombine.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoadCombine.cpp Thu Apr 21 12:58:54 2016
@@ -221,7 +221,7 @@ bool LoadCombine::combineLoads(SmallVect
 }
 
 bool LoadCombine::runOnBasicBlock(BasicBlock &BB) {
-  if (skipOptnoneFunction(BB))
+  if (skipBasicBlock(BB))
     return false;
 
   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopDeletion.cpp Thu Apr 21 12:58:54 2016
@@ -119,7 +119,7 @@ bool LoopDeletion::isLoopDead(Loop *L,
 /// NOTE: This entire process relies pretty heavily on LoopSimplify and LCSSA
 /// in order to make various safety checks work.
 bool LoopDeletion::runOnLoop(Loop *L, LPPassManager &) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp Thu Apr 21 12:58:54 2016
@@ -169,7 +169,7 @@ static void deleteDeadInstruction(Instru
 //===----------------------------------------------------------------------===//
 
 bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   CurLoop = L;

Modified: llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopInstSimplify.cpp Thu Apr 21 12:58:54 2016
@@ -65,7 +65,7 @@ Pass *llvm::createLoopInstSimplifyPass()
 }
 
 bool LoopInstSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   DominatorTreeWrapperPass *DTWP =

Modified: llvm/trunk/lib/Transforms/Scalar/LoopLoadElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopLoadElimination.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopLoadElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopLoadElimination.cpp Thu Apr 21 12:58:54 2016
@@ -531,6 +531,9 @@ public:
   }
 
   bool runOnFunction(Function &F) override {
+    if (skipFunction(F))
+      return false;
+
     auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
     auto *LAA = &getAnalysis<LoopAccessAnalysis>();
     auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopRerollPass.cpp Thu Apr 21 12:58:54 2016
@@ -1536,7 +1536,7 @@ bool LoopReroll::reroll(Instruction *IV,
 }
 
 bool LoopReroll::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp Thu Apr 21 12:58:54 2016
@@ -585,7 +585,7 @@ public:
   }
 
   bool runOnLoop(Loop *L, LPPassManager &LPM) override {
-    if (skipOptnoneFunction(L))
+    if (skipLoop(L))
       return false;
     Function &F = *L->getHeader()->getParent();
 

Modified: llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopSimplifyCFG.cpp Thu Apr 21 12:58:54 2016
@@ -91,7 +91,7 @@ static bool simplifyLoopCFG(Loop *L, Dom
 /// runOnLoop - Perform basic CFG simplifications to assist other loop passes.
 /// For now, this only attempts to merge blocks in the trivial case.
 bool LoopSimplifyCFG::runOnLoop(Loop *L, LPPassManager &) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Thu Apr 21 12:58:54 2016
@@ -5002,7 +5002,7 @@ void LoopStrengthReduce::getAnalysisUsag
 }
 
 bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   auto &IU = getAnalysis<IVUsers>();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Thu Apr 21 12:58:54 2016
@@ -787,7 +787,7 @@ public:
   Optional<bool> ProvidedRuntime;
 
   bool runOnLoop(Loop *L, LPPassManager &) override {
-    if (skipOptnoneFunction(L))
+    if (skipLoop(L))
       return false;
 
     Function &F = *L->getHeader()->getParent();

Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Thu Apr 21 12:58:54 2016
@@ -420,7 +420,7 @@ static Value *FindLIVLoopCondition(Value
 }
 
 bool LoopUnswitch::runOnLoop(Loop *L, LPPassManager &LPM_Ref) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
 
   AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(

Modified: llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopVersioningLICM.cpp Thu Apr 21 12:58:54 2016
@@ -531,7 +531,7 @@ void LoopVersioningLICM::setNoAliasToLoo
 }
 
 bool LoopVersioningLICM::runOnLoop(Loop *L, LPPassManager &LPM) {
-  if (skipOptnoneFunction(L))
+  if (skipLoop(L))
     return false;
   Changed = false;
   // Get Analysis information.

Modified: llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp Thu Apr 21 12:58:54 2016
@@ -116,7 +116,7 @@ namespace {
       initializeLowerAtomicPass(*PassRegistry::getPassRegistry());
     }
     bool runOnBasicBlock(BasicBlock &BB) override {
-      if (skipOptnoneFunction(BB))
+      if (skipBasicBlock(BB))
         return false;
       bool Changed = false;
       for (BasicBlock::iterator DI = BB.begin(), DE = BB.end(); DI != DE; ) {

Modified: llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp Thu Apr 21 12:58:54 2016
@@ -1361,7 +1361,7 @@ bool MemCpyOpt::iterateOnFunction(Functi
 
 /// This is the main transformation entry point for a function.
 bool MemCpyOpt::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   bool MadeChange = false;

Modified: llvm/trunk/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/MergedLoadStoreMotion.cpp Thu Apr 21 12:58:54 2016
@@ -560,6 +560,9 @@ bool MergedLoadStoreMotion::mergeStores(
 /// \brief Run the transformation for each function
 ///
 bool MergedLoadStoreMotion::runOnFunction(Function &F) {
+  if (skipFunction(F))
+    return false;
+
   auto *MDWP = getAnalysisIfAvailable<MemoryDependenceWrapperPass>();
   MD = MDWP ? &MDWP->getMemDep() : nullptr;
   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();

Modified: llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/NaryReassociate.cpp Thu Apr 21 12:58:54 2016
@@ -208,7 +208,7 @@ FunctionPass *llvm::createNaryReassociat
 }
 
 bool NaryReassociate::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);

Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Thu Apr 21 12:58:54 2016
@@ -2257,7 +2257,7 @@ void Reassociate::ReassociateExpression(
 }
 
 bool Reassociate::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   // Reassociate needs for each instruction to have its operands already

Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Thu Apr 21 12:58:54 2016
@@ -1568,7 +1568,7 @@ FunctionPass *llvm::createSCCPPass() {
 // and return true if the function was modified.
 //
 bool SCCP::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
@@ -1705,6 +1705,9 @@ static bool AddressIsTaken(const GlobalV
 }
 
 bool IPSCCP::runOnModule(Module &M) {
+  if (skipModule(M))
+    return false;
+
   const DataLayout &DL = M.getDataLayout();
   const TargetLibraryInfo *TLI =
       &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();

Modified: llvm/trunk/lib/Transforms/Scalar/SROA.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SROA.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SROA.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SROA.cpp Thu Apr 21 12:58:54 2016
@@ -43,6 +43,7 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Operator.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
@@ -4229,6 +4230,9 @@ PreservedAnalyses SROA::runImpl(Function
 }
 
 PreservedAnalyses SROA::run(Function &F, AnalysisManager<Function> &AM) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   return runImpl(F, AM.getResult<DominatorTreeAnalysis>(F),
                  AM.getResult<AssumptionAnalysis>(F));
 }
@@ -4246,7 +4250,7 @@ public:
     initializeSROALegacyPassPass(*PassRegistry::getPassRegistry());
   }
   bool runOnFunction(Function &F) override {
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
 
     auto PA = Impl.runImpl(

Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Apr 21 12:58:54 2016
@@ -1026,7 +1026,7 @@ ConvertScalar_InsertValue(Value *SV, Val
 
 
 bool SROA::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   bool Changed = performPromotion(F);

Modified: llvm/trunk/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp Thu Apr 21 12:58:54 2016
@@ -1064,7 +1064,7 @@ bool SeparateConstOffsetFromGEP::splitGE
 }
 
 bool SeparateConstOffsetFromGEP::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   if (DisableSeparateConstOffsetFromGEP)

Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SimplifyCFGPass.cpp Thu Apr 21 12:58:54 2016
@@ -36,6 +36,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/OptBisect.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Transforms/Utils/Local.h"
@@ -187,6 +188,9 @@ SimplifyCFGPass::SimplifyCFGPass(int Bon
 
 PreservedAnalyses SimplifyCFGPass::run(Function &F,
                                        AnalysisManager<Function> &AM) {
+  if (skipPassForFunction(name(), F))
+    return PreservedAnalyses::all();
+
   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
   auto &AC = AM.getResult<AssumptionAnalysis>(F);
 
@@ -212,7 +216,7 @@ struct CFGSimplifyPass : public Function
     if (PredicateFtor && !PredicateFtor(F))
       return false;
 
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
 
     AssumptionCache *AC =

Modified: llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SpeculativeExecution.cpp Thu Apr 21 12:58:54 2016
@@ -141,7 +141,7 @@ void SpeculativeExecution::getAnalysisUs
 }
 
 bool SpeculativeExecution::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);

Modified: llvm/trunk/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp Thu Apr 21 12:58:54 2016
@@ -682,7 +682,7 @@ void StraightLineStrengthReduce::rewrite
 }
 
 bool StraightLineStrengthReduce::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);

Modified: llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp Thu Apr 21 12:58:54 2016
@@ -157,7 +157,7 @@ static bool CanTRE(Function &F) {
 }
 
 bool TailCallElim::runOnFunction(Function &F) {
-  if (skipOptnoneFunction(F))
+  if (skipFunction(F))
     return false;
 
   if (F.getFnAttribute("disable-tail-calls").getValueAsString() == "true")

Modified: llvm/trunk/lib/Transforms/Utils/Mem2Reg.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Mem2Reg.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/Mem2Reg.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/Mem2Reg.cpp Thu Apr 21 12:58:54 2016
@@ -59,13 +59,13 @@ INITIALIZE_PASS_END(PromotePass, "mem2re
                 false, false)
 
 bool PromotePass::runOnFunction(Function &F) {
+  if (skipFunction(F))
+    return false;
+
   std::vector<AllocaInst*> Allocas;
 
   BasicBlock &BB = F.getEntryBlock();  // Get the entry node for the function
 
-  if (F.hasFnAttribute(Attribute::OptimizeNone))
-    return false;
-
   bool Changed  = false;
 
   DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();

Modified: llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp (original)
+++ llvm/trunk/lib/Transforms/Vectorize/BBVectorize.cpp Thu Apr 21 12:58:54 2016
@@ -397,7 +397,7 @@ namespace {
                      Instruction *I, Instruction *J);
 
     bool vectorizeBB(BasicBlock &BB) {
-      if (skipOptnoneFunction(BB))
+      if (skipBasicBlock(BB))
         return false;
       if (!DT->isReachableFromEntry(&BB)) {
         DEBUG(dbgs() << "BBV: skipping unreachable " << BB.getName() <<

Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)
+++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Thu Apr 21 12:58:54 2016
@@ -1707,6 +1707,9 @@ struct LoopVectorize : public FunctionPa
   BlockFrequency ColdEntryFreq;
 
   bool runOnFunction(Function &F) override {
+    if (skipFunction(F))
+      return false;
+
     SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
     LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
     TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);

Modified: llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp?rev=267022&r1=267021&r2=267022&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Vectorize/SLPVectorizer.cpp Thu Apr 21 12:58:54 2016
@@ -3396,7 +3396,7 @@ struct SLPVectorizer : public FunctionPa
   }
 
   bool runOnFunction(Function &F) override {
-    if (skipOptnoneFunction(F))
+    if (skipFunction(F))
       return false;
 
     SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();

Added: llvm/trunk/test/Other/opt-bisect-helper.py
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-bisect-helper.py?rev=267022&view=auto
==============================================================================
--- llvm/trunk/test/Other/opt-bisect-helper.py (added)
+++ llvm/trunk/test/Other/opt-bisect-helper.py Thu Apr 21 12:58:54 2016
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import argparse
+import subprocess
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument('--start', type=int, default=0)
+parser.add_argument('--end', type=int, default=(1 << 32))
+parser.add_argument('--optcmd', default=("opt"))
+parser.add_argument('--filecheckcmd', default=("FileCheck"))
+parser.add_argument('--prefix', default=("CHECK-BISECT"))
+parser.add_argument('--test', default=(""))
+
+args = parser.parse_args()
+
+start = args.start
+end = args.end
+
+opt_command = [args.optcmd, "-O2", "-opt-bisect-limit=%(count)s", "-S", args.test]
+check_command = [args.filecheckcmd, args.test, "--check-prefix=%s" % args.prefix]
+last = None
+while start != end and start != end-1:
+    count = int(round(start + (end - start)/2))
+    cmd = [x % {'count':count} for x in opt_command]
+    print("opt: " + str(cmd))
+    opt_result = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    filecheck_result = subprocess.Popen(check_command, stdin=opt_result.stdout)
+    opt_result.stdout.close()
+    opt_result.stderr.close()
+    filecheck_result.wait()
+    if filecheck_result.returncode == 0:
+        start = count
+    else:
+        end = count
+
+print("Last good count: %d" % start)

Propchange: llvm/trunk/test/Other/opt-bisect-helper.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: llvm/trunk/test/Other/opt-bisect-helper.py
------------------------------------------------------------------------------
    svn:executable = *

Propchange: llvm/trunk/test/Other/opt-bisect-helper.py
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Rev URL

Propchange: llvm/trunk/test/Other/opt-bisect-helper.py
------------------------------------------------------------------------------
    svn:mime-type = text/x-python

Added: llvm/trunk/test/Other/opt-bisect-legacy-pass-manager.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-bisect-legacy-pass-manager.ll?rev=267022&view=auto
==============================================================================
--- llvm/trunk/test/Other/opt-bisect-legacy-pass-manager.ll (added)
+++ llvm/trunk/test/Other/opt-bisect-legacy-pass-manager.ll Thu Apr 21 12:58:54 2016
@@ -0,0 +1,148 @@
+; This file verifies the behavior of the OptBisect class, which is used to
+; diagnose optimization related failures.  The tests check various
+; invocations that result in different sets of optimization passes that
+; are run in different ways.
+;
+; This set of tests exercises the legacy pass manager interface to the OptBisect
+; class.  Because the exact set of optimizations that will be run may
+; change over time, these tests are written in a more general manner than the
+; corresponding tests for the new pass manager.
+;
+; Don't use NEXT checks or hard-code pass numbering so that this won't fail if
+; new passes are inserted.
+
+
+; Verify that the file can be compiled to an object file at -O3 with all
+; skippable passes skipped.
+
+; RUN: opt -O3 -opt-bisect-limit=0 < %s | llc -O3 -opt-bisect-limit=0
+
+
+; Verify that no skippable passes are run with -opt-bisect-limit=0.
+
+; RUN: opt -disable-output -disable-verify -O3 -opt-bisect-limit=0 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-SKIP-ALL
+; CHECK-SKIP-ALL: BISECT: NOT running pass ({{[0-9]+}})
+; CHECK-SKIP-ALL-NOT: BISECT: running pass ({{[0-9]+}})
+
+
+; Verify that we can use the opt-bisect-helper.py script (derived from
+; utils/bisect) to locate the optimization that inlines the call to
+; f2() in f3().
+
+; RUN: %python %S/opt-bisect-helper.py --start=0 --end=256 --optcmd=opt \
+; RUN:         --filecheckcmd=FileCheck --test=%s \
+; RUN:         --prefix=CHECK-BISECT-INLINE-HELPER \
+; RUN:         | FileCheck %s --check-prefix=CHECK-BISECT-INLINE-RESULT
+; The helper script uses this to find the optimization that inlines the call.
+; CHECK-BISECT-INLINE-HELPER: call i32 @f2()
+; These checks verifies that the optimization was found.
+; CHECK-BISECT-INLINE-RESULT-NOT: Last good count: 0
+; CHECK-BISECT-INLINE-RESULT: Last good count: {{[0-9]+}}
+
+
+; Test a module pass.
+
+; RUN: opt -disable-output -disable-verify -deadargelim -opt-bisect-limit=-1 %s \
+; RUN:     2>&1 | FileCheck %s --check-prefix=CHECK-DEADARG
+; CHECK-DEADARG: BISECT: running pass ({{[0-9]+}}) Dead Argument Elimination on module
+
+; RUN: opt -disable-output -disable-verify -deadargelim -opt-bisect-limit=0 %s \
+; RUN:     2>&1 | FileCheck %s --check-prefix=CHECK-NOT-DEADARG
+; CHECK-NOT-DEADARG: BISECT: NOT running pass ({{[0-9]+}}) Dead Argument Elimination on module
+
+
+; Test an SCC pass.
+
+; RUN: opt -disable-output -disable-verify -inline -opt-bisect-limit=-1 %s \
+; RUN:     2>&1 | FileCheck %s --check-prefix=CHECK-INLINE
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (g)
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f1)
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f2)
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f3)
+; CHECK-INLINE: BISECT: running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
+
+; RUN: opt -disable-output -disable-verify -inline -opt-bisect-limit=0 %s \
+; RUN:     2>&1 | FileCheck %s --check-prefix=CHECK-NOT-INLINE
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (g)
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f1)
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f2)
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (f3)
+; CHECK-NOT-INLINE: BISECT: NOT running pass ({{[0-9]+}}) Function Integration/Inlining on SCC (<<null function>>)
+
+
+; Test a function pass.
+
+; RUN: opt -disable-output -disable-verify -early-cse -opt-bisect-limit=-1 \
+; RUN:     %s 2>&1 | FileCheck %s --check-prefix=CHECK-EARLY-CSE
+; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f1)
+; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f2)
+; CHECK-EARLY-CSE: BISECT: running pass ({{[0-9]+}}) Early CSE on function (f3)
+
+; RUN: opt -disable-output -disable-verify -early-cse -opt-bisect-limit=0 %s \
+; RUN:     2>&1 | FileCheck %s --check-prefix=CHECK-NOT-EARLY-CSE
+; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f1)
+; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f2)
+; CHECK-NOT-EARLY-CSE: BISECT: NOT running pass ({{[0-9]+}}) Early CSE on function (f3)
+
+
+; Test a loop pass.
+
+; RUN: opt -disable-output -disable-verify -loop-reduce -opt-bisect-limit=-1 \
+; RUN:      %s 2>&1 | FileCheck %s --check-prefix=CHECK-LOOP-REDUCE
+; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-LOOP-REDUCE: BISECT: running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+
+; RUN: opt -disable-output -disable-verify -loop-reduce -opt-bisect-limit=0 \
+; RUN:     %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOT-LOOP-REDUCE
+; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+; CHECK-NOT-LOOP-REDUCE: BISECT: NOT running pass ({{[0-9]+}}) Loop Strength Reduction on loop
+
+
+declare i32 @g()
+
+define void @f1() {
+entry:
+  br label %loop.0
+loop.0:
+  br i1 undef, label %loop.0.0, label %loop.1
+loop.0.0:
+  br i1 undef, label %loop.0.0, label %loop.0.1
+loop.0.1:
+  br i1 undef, label %loop.0.1, label %loop.0
+loop.1:
+  br i1 undef, label %loop.1, label %loop.1.bb1
+loop.1.bb1:
+  br i1 undef, label %loop.1, label %loop.1.bb2
+loop.1.bb2:
+  br i1 undef, label %end, label %loop.1.0
+loop.1.0:
+  br i1 undef, label %loop.1.0, label %loop.1
+end:
+  ret void
+}
+
+define i32 @f2() {
+entry:
+  ret i32 0
+}
+
+define i32 @f3() {
+entry:
+  %temp = call i32 @g()
+  %icmp = icmp ugt i32 %temp, 2
+  br i1 %icmp, label %bb.true, label %bb.false
+bb.true:
+  %temp2 = call i32 @f2()
+  ret i32 %temp2
+bb.false:
+  ret i32 0
+}

Added: llvm/trunk/test/Other/opt-bisect-new-pass-manager.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/opt-bisect-new-pass-manager.ll?rev=267022&view=auto
==============================================================================
--- llvm/trunk/test/Other/opt-bisect-new-pass-manager.ll (added)
+++ llvm/trunk/test/Other/opt-bisect-new-pass-manager.ll Thu Apr 21 12:58:54 2016
@@ -0,0 +1,109 @@
+; This file verifies the behavior of the OptBisect class, which is used to
+; diagnose optimization related failures.  The tests check various
+; invocations that result in different sets of optimization passes that
+; are run in different ways.
+;
+; Because the exact set of optimizations that will be run is expected to
+; change over time, the checks for disabling passes are written in a
+; conservative way that avoids assumptions about which specific passes
+; will be disabled.
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=inferattrs -opt-bisect-limit=-1 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-MODULE-PASS
+; CHECK-MODULE-PASS: BISECT: running pass (1) InferFunctionAttrsPass on module
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=inferattrs -opt-bisect-limit=0 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-LIMIT-MODULE-PASS
+; CHECK-LIMIT-MODULE-PASS: BISECT: NOT running pass (1) InferFunctionAttrsPass on module
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=early-cse -opt-bisect-limit=-1 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS
+; CHECK-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on function (f1)
+; CHECK-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on function (f2)
+; CHECK-FUNCTION-PASS: BISECT: running pass (3) EarlyCSEPass on function (f3)
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=early-cse -opt-bisect-limit=2 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-LIMIT-FUNCTION-PASS
+; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (1) EarlyCSEPass on function (f1)
+; CHECK-LIMIT-FUNCTION-PASS: BISECT: running pass (2) EarlyCSEPass on function (f2)
+; CHECK-LIMIT-FUNCTION-PASS: BISECT: NOT running pass (3) EarlyCSEPass on function (f3)
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=function-attrs -opt-bisect-limit=-1 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-CGSCC-PASS
+; CHECK-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on SCC (f2)
+; CHECK-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on SCC (f3)
+; CHECK-CGSCC-PASS: BISECT: running pass (3) PostOrderFunctionAttrsPass on SCC (f1)
+
+; RUN: opt -disable-output -disable-verify \
+; RUN:     -passes=function-attrs -opt-bisect-limit=2 %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-LIMIT-CGSCC-PASS
+; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (1) PostOrderFunctionAttrsPass on SCC (f2)
+; CHECK-LIMIT-CGSCC-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on SCC (f3)
+; CHECK-LIMIT-CGSCC-PASS: BISECT: NOT running pass (3) PostOrderFunctionAttrsPass on SCC (f1)
+
+; RUN: opt -disable-output -disable-verify -opt-bisect-limit=-1 \
+; RUN:     -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-MULTI-PASS
+; CHECK-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on module
+; CHECK-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on SCC (f2)
+; CHECK-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on function (f2)
+; CHECK-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on SCC (f3)
+; CHECK-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on function (f3)
+; CHECK-MULTI-PASS: BISECT: running pass (6) PostOrderFunctionAttrsPass on SCC (f1)
+; CHECK-MULTI-PASS: BISECT: running pass (7) EarlyCSEPass on function (f1)
+
+; RUN: opt -disable-output -disable-verify -opt-bisect-limit=5 \
+; RUN:     -passes='inferattrs,cgscc(function-attrs,function(early-cse))' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-LIMIT-MULTI-PASS
+; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (1) InferFunctionAttrsPass on module
+; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (2) PostOrderFunctionAttrsPass on SCC (f2)
+; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (3) EarlyCSEPass on function (f2)
+; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (4) PostOrderFunctionAttrsPass on SCC (f3)
+; CHECK-LIMIT-MULTI-PASS: BISECT: running pass (5) EarlyCSEPass on function (f3)
+; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (6) PostOrderFunctionAttrsPass on SCC (f1)
+; CHECK-LIMIT-MULTI-PASS: BISECT: NOT running pass (7) EarlyCSEPass on function (f1)
+
+declare i32 @g()
+
+define void @f1() {
+entry:
+  br label %loop.0
+loop.0:
+  br i1 undef, label %loop.0.0, label %loop.1
+loop.0.0:
+  br i1 undef, label %loop.0.0, label %loop.0.1
+loop.0.1:
+  br i1 undef, label %loop.0.1, label %loop.0
+loop.1:
+  br i1 undef, label %loop.1, label %loop.1.bb1
+loop.1.bb1:
+  br i1 undef, label %loop.1, label %loop.1.bb2
+loop.1.bb2:
+  br i1 undef, label %end, label %loop.1.0
+loop.1.0:
+  br i1 undef, label %loop.1.0, label %loop.1
+end:
+  ret void
+}
+
+define i32 @f2() {
+entry:
+  ret i32 0
+}
+
+define i32 @f3() {
+entry:
+  %temp = call i32 @g()
+  %icmp = icmp ugt i32 %temp, 2
+  br i1 %icmp, label %bb.true, label %bb.false
+bb.true:
+  %temp2 = call i32 @f2()
+  ret i32 %temp2
+bb.false:
+  ret i32 0
+}




More information about the llvm-commits mailing list