From 8002c504cda71900e6d981d420a3671798f18188 Mon Sep 17 00:00:00 2001 From: Eugene Zelenko Date: Wed, 13 Sep 2017 21:43:53 +0000 Subject: [PATCH] [Transforms] Fix some Clang-tidy modernize-use-using and Include What You Use warnings; other minor fixes (NFC). llvm-svn: 313198 --- .../llvm/Transforms/Scalar/ConstantHoisting.h | 44 ++++++---- llvm/include/llvm/Transforms/Scalar/GVN.h | 57 +++++++++---- .../llvm/Transforms/Scalar/GVNExpression.h | 80 +++++++++---------- .../llvm/Transforms/Scalar/JumpThreading.h | 37 ++++++--- .../Transforms/Scalar/ConstantHoisting.cpp | 50 ++++++++---- llvm/lib/Transforms/Scalar/GVN.cpp | 73 +++++++++++------ llvm/lib/Transforms/Scalar/JumpThreading.cpp | 73 +++++++++++------ 7 files changed, 267 insertions(+), 147 deletions(-) diff --git a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h index a2a9afc083a0..d3322dc1c414 100644 --- a/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h +++ b/llvm/include/llvm/Transforms/Scalar/ConstantHoisting.h @@ -1,4 +1,4 @@ -//===-- ConstantHoisting.h - Prepare code for expensive constants ---------===// +//==- ConstantHoisting.h - Prepare code for expensive constants --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -31,41 +31,53 @@ // This optimization is only applied to integer constants in instructions and // simple (this means not nested) constant cast expressions. For example: // %0 = load i64* inttoptr (i64 big_constant to i64*) +// //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H #define LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H -#include "llvm/Analysis/BlockFrequencyInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/IR/Dominators.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/IR/PassManager.h" +#include +#include namespace llvm { +class BasicBlock; +class BlockFrequencyInfo; +class Constant; +class ConstantInt; +class DominatorTree; +class Function; +class Instruction; +class TargetTransformInfo; + /// A private "module" namespace for types and utilities used by /// ConstantHoisting. These are implementation details and should not be used by /// clients. namespace consthoist { + /// \brief Keeps track of the user of a constant and the operand index where the /// constant is used. struct ConstantUser { Instruction *Inst; unsigned OpndIdx; - ConstantUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) { } + ConstantUser(Instruction *Inst, unsigned Idx) : Inst(Inst), OpndIdx(Idx) {} }; -typedef SmallVector ConstantUseListType; +using ConstantUseListType = SmallVector; /// \brief Keeps track of a constant candidate and its uses. struct ConstantCandidate { ConstantUseListType Uses; ConstantInt *ConstInt; - unsigned CumulativeCost; + unsigned CumulativeCost = 0; - ConstantCandidate(ConstantInt *ConstInt) - : ConstInt(ConstInt), CumulativeCost(0) { } + ConstantCandidate(ConstantInt *ConstInt) : ConstInt(ConstInt) {} /// \brief Add the user to the use list and update the cost. void addUser(Instruction *Inst, unsigned Idx, unsigned Cost) { @@ -81,17 +93,18 @@ struct RebasedConstantInfo { Constant *Offset; RebasedConstantInfo(ConstantUseListType &&Uses, Constant *Offset) - : Uses(std::move(Uses)), Offset(Offset) { } + : Uses(std::move(Uses)), Offset(Offset) {} }; -typedef SmallVector RebasedConstantListType; +using RebasedConstantListType = SmallVector; /// \brief A base constant and all its rebased constants. struct ConstantInfo { ConstantInt *BaseConstant; RebasedConstantListType RebasedConstants; }; -} + +} // end namespace consthoist class ConstantHoistingPass : public PassInfoMixin { public: @@ -108,8 +121,8 @@ public: } private: - typedef DenseMap ConstCandMapType; - typedef std::vector ConstCandVecType; + using ConstCandMapType = DenseMap; + using ConstCandVecType = std::vector; const TargetTransformInfo *TTI; DominatorTree *DT; @@ -148,6 +161,7 @@ private: void deleteDeadCastInst() const; bool optimizeConstants(Function &Fn); }; -} + +} // end namespace llvm #endif // LLVM_TRANSFORMS_SCALAR_CONSTANTHOISTING_H diff --git a/llvm/include/llvm/Transforms/Scalar/GVN.h b/llvm/include/llvm/Transforms/Scalar/GVN.h index 32f640a5642a..251492a4e5d3 100644 --- a/llvm/include/llvm/Transforms/Scalar/GVN.h +++ b/llvm/include/llvm/Transforms/Scalar/GVN.h @@ -19,25 +19,45 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/IR/Dominators.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include +#include +#include namespace llvm { + +class AssumptionCache; +class BasicBlock; +class BranchInst; +class CallInst; +class Constant; +class ExtractValueInst; +class Function; +class FunctionPass; class IntrinsicInst; +class LoadInst; +class LoopInfo; class OptimizationRemarkEmitter; +class PHINode; +class TargetLibraryInfo; +class Value; /// A private "module" namespace for types and utilities used by GVN. These /// are implementation details and should not be used by clients. namespace gvn LLVM_LIBRARY_VISIBILITY { + struct AvailableValue; struct AvailableValueInBlock; class GVNLegacyPass; -} + +} // end namespace gvn /// The core GVN pass object. /// @@ -45,6 +65,7 @@ class GVNLegacyPass; /// this particular pass here. class GVN : public PassInfoMixin { public: + struct Expression; /// \brief Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); @@ -60,8 +81,6 @@ public: AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); } MemoryDependenceResults &getMemDep() const { return *MD; } - struct Expression; - /// This class holds the mapping between values and value numbers. It is used /// as an efficient mechanism to determine the expression-wise equivalence of /// two values. @@ -74,20 +93,23 @@ public: // instead of a DenseMap because filling such mapping is faster than // filling a DenseMap and the compile time is a little better. uint32_t nextExprNumber; + std::vector Expressions; std::vector ExprIdx; + // Value number to PHINode mapping. Used for phi-translate in scalarpre. DenseMap NumberingPhi; + // Cache for phi-translate in scalarpre. - typedef DenseMap, uint32_t> - PhiTranslateMap; + using PhiTranslateMap = + DenseMap, uint32_t>; PhiTranslateMap PhiTranslateTable; AliasAnalysis *AA; MemoryDependenceResults *MD; DominatorTree *DT; - uint32_t nextValueNumber; + uint32_t nextValueNumber = 1; Expression createExpr(Instruction *I); Expression createCmpExpr(unsigned Opcode, CmpInst::Predicate Predicate, @@ -150,16 +172,16 @@ private: // Block-local map of equivalent values to their leader, does not // propagate to any successors. Entries added mid-block are applied // to the remaining instructions in the block. - SmallMapVector ReplaceWithConstMap; + SmallMapVector ReplaceWithConstMap; SmallVector InstrsToErase; // Map the block to reversed postorder traversal number. It is used to // find back edge easily. DenseMap BlockRPONumber; - typedef SmallVector LoadDepVect; - typedef SmallVector AvailValInBlkVect; - typedef SmallVector UnavailBlkVect; + using LoadDepVect = SmallVector; + using AvailValInBlkVect = SmallVector; + using UnavailBlkVect = SmallVector; bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT, const TargetLibraryInfo &RunTLI, AAResults &RunAA, @@ -218,17 +240,20 @@ private: bool processLoad(LoadInst *L); bool processNonLocalLoad(LoadInst *L); bool processAssumeIntrinsic(IntrinsicInst *II); + /// Given a local dependency (Def or Clobber) determine if a value is /// available for the load. Returns true if an value is known to be /// available and populates Res. Returns false otherwise. bool AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, Value *Address, gvn::AvailableValue &Res); + /// Given a list of non-local dependencies, determine if a value is /// available for the load in each specified block. If it is, add it to /// ValuesPerBlock. If not, add it to UnavailableBlocks. void AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps, AvailValInBlkVect &ValuesPerBlock, UnavailBlkVect &UnavailableBlocks); + bool PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock, UnavailBlkVect &UnavailableBlocks); @@ -265,12 +290,14 @@ struct GVNHoistPass : PassInfoMixin { /// \brief Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; + /// \brief Uses an "inverted" value numbering to decide the similarity of /// expressions and sinks similar expressions into successors. struct GVNSinkPass : PassInfoMixin { /// \brief Run the pass over the function. PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -} -#endif +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_GVN_H diff --git a/llvm/include/llvm/Transforms/Scalar/GVNExpression.h b/llvm/include/llvm/Transforms/Scalar/GVNExpression.h index f603ebcbca7c..99dae15a3ac0 100644 --- a/llvm/include/llvm/Transforms/Scalar/GVNExpression.h +++ b/llvm/include/llvm/Transforms/Scalar/GVNExpression.h @@ -1,4 +1,4 @@ -//======- GVNExpression.h - GVN Expression classes --------------*- C++ -*-===// +//===- GVNExpression.h - GVN Expression classes -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,11 +6,12 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file /// /// The header file for the GVN pass that contains expression handling /// classes -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_SCALAR_GVNEXPRESSION_H @@ -25,7 +26,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Debug.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -34,6 +35,9 @@ namespace llvm { +class BasicBlock; +class Type; + namespace GVNExpression { enum ExpressionType { @@ -58,17 +62,18 @@ class Expression { private: ExpressionType EType; unsigned Opcode; - mutable hash_code HashVal; + mutable hash_code HashVal = 0; public: Expression(ExpressionType ET = ET_Base, unsigned O = ~2U) - : EType(ET), Opcode(O), HashVal(0) {} + : EType(ET), Opcode(O) {} Expression(const Expression &) = delete; Expression &operator=(const Expression &) = delete; virtual ~Expression(); static unsigned getEmptyKey() { return ~0U; } static unsigned getTombstoneKey() { return ~1U; } + bool operator!=(const Expression &Other) const { return !(*this == Other); } bool operator==(const Expression &Other) const { if (getOpcode() != Other.getOpcode()) @@ -83,6 +88,7 @@ public: return equals(Other); } + hash_code getComputedHash() const { // It's theoretically possible for a thing to hash to zero. In that case, // we will just compute the hash a few extra times, which is no worse that @@ -93,6 +99,7 @@ public: } virtual bool equals(const Expression &Other) const { return true; } + // Return true if the two expressions are exactly the same, including the // normally ignored fields. virtual bool exactlyEquals(const Expression &Other) const { @@ -106,9 +113,7 @@ public: // We deliberately leave the expression type out of the hash value. virtual hash_code getHashValue() const { return getOpcode(); } - // // Debugging support - // virtual void printInternal(raw_ostream &OS, bool PrintEType) const { if (PrintEType) OS << "etype = " << getExpressionType() << ","; @@ -131,19 +136,19 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) { class BasicExpression : public Expression { private: - typedef ArrayRecycler RecyclerType; - typedef RecyclerType::Capacity RecyclerCapacity; - Value **Operands; + using RecyclerType = ArrayRecycler; + using RecyclerCapacity = RecyclerType::Capacity; + + Value **Operands = nullptr; unsigned MaxOperands; - unsigned NumOperands; - Type *ValueType; + unsigned NumOperands = 0; + Type *ValueType = nullptr; public: BasicExpression(unsigned NumOperands) : BasicExpression(NumOperands, ET_Basic) {} BasicExpression(unsigned NumOperands, ExpressionType ET) - : Expression(ET), Operands(nullptr), MaxOperands(NumOperands), - NumOperands(0), ValueType(nullptr) {} + : Expression(ET), MaxOperands(NumOperands) {} BasicExpression() = delete; BasicExpression(const BasicExpression &) = delete; BasicExpression &operator=(const BasicExpression &) = delete; @@ -174,8 +179,9 @@ public: unsigned getNumOperands() const { return NumOperands; } - typedef Value **op_iterator; - typedef Value *const *const_op_iterator; + using op_iterator = Value **; + using const_op_iterator = Value *const *; + op_iterator op_begin() { return Operands; } op_iterator op_end() { return Operands + NumOperands; } const_op_iterator op_begin() const { return Operands; } @@ -219,9 +225,7 @@ public: hash_combine_range(op_begin(), op_end())); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeBasic, "; @@ -240,7 +244,8 @@ public: class op_inserter : public std::iterator { private: - typedef BasicExpression Container; + using Container = BasicExpression; + Container *BE; public: @@ -263,15 +268,16 @@ private: public: MemoryExpression(unsigned NumOperands, enum ExpressionType EType, const MemoryAccess *MemoryLeader) - : BasicExpression(NumOperands, EType), MemoryLeader(MemoryLeader){}; - + : BasicExpression(NumOperands, EType), MemoryLeader(MemoryLeader) {} MemoryExpression() = delete; MemoryExpression(const MemoryExpression &) = delete; MemoryExpression &operator=(const MemoryExpression &) = delete; + static bool classof(const Expression *EB) { return EB->getExpressionType() > ET_MemoryStart && EB->getExpressionType() < ET_MemoryEnd; } + hash_code getHashValue() const override { return hash_combine(this->BasicExpression::getHashValue(), MemoryLeader); } @@ -305,9 +311,7 @@ public: return EB->getExpressionType() == ET_Call; } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeCall, "; @@ -326,11 +330,13 @@ public: LoadExpression(unsigned NumOperands, LoadInst *L, const MemoryAccess *MemoryLeader) : LoadExpression(ET_Load, NumOperands, L, MemoryLeader) {} + LoadExpression(enum ExpressionType EType, unsigned NumOperands, LoadInst *L, const MemoryAccess *MemoryLeader) : MemoryExpression(NumOperands, EType, MemoryLeader), Load(L) { Alignment = L ? L->getAlignment() : 0; } + LoadExpression() = delete; LoadExpression(const LoadExpression &) = delete; LoadExpression &operator=(const LoadExpression &) = delete; @@ -352,9 +358,7 @@ public: cast(Other).getLoadInst() == getLoadInst(); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeLoad, "; @@ -388,13 +392,13 @@ public: Value *getStoredValue() const { return StoredValue; } bool equals(const Expression &Other) const override; + bool exactlyEquals(const Expression &Other) const override { return Expression::exactlyEquals(Other) && cast(Other).getStoreInst() == getStoreInst(); } // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeStore, "; @@ -409,14 +413,13 @@ public: class AggregateValueExpression final : public BasicExpression { private: unsigned MaxIntOperands; - unsigned NumIntOperands; - unsigned *IntOperands; + unsigned NumIntOperands = 0; + unsigned *IntOperands = nullptr; public: AggregateValueExpression(unsigned NumOperands, unsigned NumIntOperands) : BasicExpression(NumOperands, ET_AggregateValue), - MaxIntOperands(NumIntOperands), NumIntOperands(0), - IntOperands(nullptr) {} + MaxIntOperands(NumIntOperands) {} AggregateValueExpression() = delete; AggregateValueExpression(const AggregateValueExpression &) = delete; AggregateValueExpression & @@ -427,8 +430,8 @@ public: return EB->getExpressionType() == ET_AggregateValue; } - typedef unsigned *int_arg_iterator; - typedef const unsigned *const_int_arg_iterator; + using int_arg_iterator = unsigned *; + using const_int_arg_iterator = const unsigned *; int_arg_iterator int_op_begin() { return IntOperands; } int_arg_iterator int_op_end() { return IntOperands + NumIntOperands; } @@ -463,9 +466,7 @@ public: hash_combine_range(int_op_begin(), int_op_end())); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeAggregateValue, "; @@ -481,7 +482,8 @@ public: class int_op_inserter : public std::iterator { private: - typedef AggregateValueExpression Container; + using Container = AggregateValueExpression; + Container *AVE; public: @@ -524,9 +526,7 @@ public: return hash_combine(this->BasicExpression::getHashValue(), BB); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypePhi, "; @@ -573,9 +573,7 @@ public: VariableValue->getType(), VariableValue); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeVariable, "; @@ -612,9 +610,7 @@ public: ConstantValue->getType(), ConstantValue); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeConstant, "; @@ -649,9 +645,7 @@ public: return hash_combine(this->Expression::getHashValue(), Inst); } - // // Debugging support - // void printInternal(raw_ostream &OS, bool PrintEType) const override { if (PrintEType) OS << "ExpressionTypeUnknown, "; diff --git a/llvm/include/llvm/Transforms/Scalar/JumpThreading.h b/llvm/include/llvm/Transforms/Scalar/JumpThreading.h index 1da86132591b..a9466713b8e6 100644 --- a/llvm/include/llvm/Transforms/Scalar/JumpThreading.h +++ b/llvm/include/llvm/Transforms/Scalar/JumpThreading.h @@ -6,41 +6,57 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file /// See the comments on JumpThreadingPass. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H #define LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BlockFrequencyInfo.h" -#include "llvm/Analysis/BlockFrequencyInfoImpl.h" #include "llvm/Analysis/BranchProbabilityInfo.h" -#include "llvm/Analysis/LazyValueInfo.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/ValueHandle.h" +#include +#include namespace llvm { +class BasicBlock; +class BinaryOperator; +class BranchInst; +class CmpInst; +class Constant; +class Function; +class Instruction; +class IntrinsicInst; +class LazyValueInfo; +class LoadInst; +class PHINode; +class TargetLibraryInfo; +class Value; + /// A private "module" namespace for types and utilities used by /// JumpThreading. /// These are implementation details and should not be used by clients. namespace jumpthreading { + // These are at global scope so static functions can use them too. -typedef SmallVectorImpl> PredValueInfo; -typedef SmallVector, 8> PredValueInfoTy; +using PredValueInfo = SmallVectorImpl>; +using PredValueInfoTy = SmallVector, 8>; // This is used to keep track of what kind of constant we're currently hoping // to find. enum ConstantPreference { WantInteger, WantBlockAddress }; -} + +} // end namespace jumpthreading /// This pass performs 'jump threading', which looks at blocks that have /// multiple predecessors and multiple successors. If one or more of the @@ -57,7 +73,6 @@ enum ConstantPreference { WantInteger, WantBlockAddress }; /// /// In this case, the unconditional branch at the end of the first if can be /// revectored to the false side of the second if. -/// class JumpThreadingPass : public PassInfoMixin { TargetLibraryInfo *TLI; LazyValueInfo *LVI; @@ -141,4 +156,4 @@ private: } // end namespace llvm -#endif +#endif // LLVM_TRANSFORMS_SCALAR_JUMPTHREADING_H diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp index 122c9314e022..58a910ded21d 100644 --- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -34,18 +34,38 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Scalar/ConstantHoisting.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Value.h" #include "llvm/Pass.h" +#include "llvm/Support/BlockFrequency.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Local.h" +#include +#include +#include +#include #include +#include using namespace llvm; using namespace consthoist; @@ -62,10 +82,12 @@ static cl::opt ConstHoistWithBlockFrequency( "without hoisting.")); namespace { + /// \brief The constant hoisting pass. class ConstantHoistingLegacyPass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid + ConstantHoistingLegacyPass() : FunctionPass(ID) { initializeConstantHoistingLegacyPassPass(*PassRegistry::getPassRegistry()); } @@ -87,9 +109,11 @@ public: private: ConstantHoistingPass Impl; }; -} + +} // end anonymous namespace char ConstantHoistingLegacyPass::ID = 0; + INITIALIZE_PASS_BEGIN(ConstantHoistingLegacyPass, "consthoist", "Constant Hoisting", false, false) INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) @@ -128,7 +152,6 @@ bool ConstantHoistingLegacyPass::runOnFunction(Function &Fn) { return MadeChange; } - /// \brief Find the constant materialization insertion point. Instruction *ConstantHoistingPass::findMatInsertPt(Instruction *Inst, unsigned Idx) const { @@ -217,8 +240,9 @@ static void findBestInsertionSet(DominatorTree &DT, BlockFrequencyInfo &BFI, } // Visit Orders in bottom-up order. - typedef std::pair, BlockFrequency> - InsertPtsCostPair; + using InsertPtsCostPair = + std::pair, BlockFrequency>; + // InsertPtsMap is a map from a BB to the best insertion points for the // subtree of BB (subtree not including the BB itself). DenseMap InsertPtsMap; @@ -310,7 +334,6 @@ SmallPtrSet ConstantHoistingPass::findConstantInsertionPoint( return InsertPts; } - /// \brief Record constant integer ConstInt for instruction Inst at operand /// index Idx. /// @@ -351,7 +374,6 @@ void ConstantHoistingPass::collectConstantCandidates( } } - /// \brief Check the operand for instruction Inst at index Idx. void ConstantHoistingPass::collectConstantCandidates( ConstCandMapType &ConstCandMap, Instruction *Inst, unsigned Idx) { @@ -393,7 +415,6 @@ void ConstantHoistingPass::collectConstantCandidates( } } - /// \brief Scan the instruction for expensive integer constants and record them /// in the constant candidate vector. void ConstantHoistingPass::collectConstantCandidates( @@ -427,9 +448,8 @@ void ConstantHoistingPass::collectConstantCandidates(Function &Fn) { // bit widths (APInt Operator- does not like that). If the value cannot be // represented in uint64 we return an "empty" APInt. This is then interpreted // as the value is not in range. -static llvm::Optional calculateOffsetDiff(const APInt &V1, - const APInt &V2) { - llvm::Optional Res = None; +static Optional calculateOffsetDiff(const APInt &V1, const APInt &V2) { + Optional Res = None; unsigned BW = V1.getBitWidth() > V2.getBitWidth() ? V1.getBitWidth() : V2.getBitWidth(); uint64_t LimVal1 = V1.getLimitedValue(); @@ -496,9 +516,9 @@ ConstantHoistingPass::maximizeConstantsInRange(ConstCandVecType::iterator S, DEBUG(dbgs() << "Cost: " << Cost << "\n"); for (auto C2 = S; C2 != E; ++C2) { - llvm::Optional Diff = calculateOffsetDiff( - C2->ConstInt->getValue(), - ConstCand->ConstInt->getValue()); + Optional Diff = calculateOffsetDiff( + C2->ConstInt->getValue(), + ConstCand->ConstInt->getValue()); if (Diff) { const int ImmCosts = TTI->getIntImmCodeSizeCost(Opcode, OpndIdx, Diff.getValue(), Ty); diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index 5446f6057150..497e1d3eb379 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -20,39 +20,63 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/CFG.h" -#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InstructionSimplify.h" -#include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/PHITransAddr.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/Dominators.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/Value.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/SSAUpdater.h" #include "llvm/Transforms/Utils/VNCoercion.h" - +#include +#include +#include +#include #include + using namespace llvm; using namespace llvm::gvn; using namespace llvm::VNCoercion; @@ -80,10 +104,10 @@ MaxRecurseDepth("max-recurse-depth", cl::Hidden, cl::init(1000), cl::ZeroOrMore, struct llvm::GVN::Expression { uint32_t opcode; Type *type; - bool commutative; + bool commutative = false; SmallVector varargs; - Expression(uint32_t o = ~2U) : opcode(o), commutative(false) {} + Expression(uint32_t o = ~2U) : opcode(o) {} bool operator==(const Expression &other) const { if (opcode != other.opcode) @@ -105,20 +129,23 @@ struct llvm::GVN::Expression { }; namespace llvm { + template <> struct DenseMapInfo { static inline GVN::Expression getEmptyKey() { return ~0U; } - static inline GVN::Expression getTombstoneKey() { return ~1U; } static unsigned getHashValue(const GVN::Expression &e) { using llvm::hash_value; + return static_cast(hash_value(e)); } + static bool isEqual(const GVN::Expression &LHS, const GVN::Expression &RHS) { return LHS == RHS; } }; -} // End llvm namespace. + +} // end namespace llvm /// Represents a particular available value that we know how to materialize. /// Materialization of an AvailableValue never fails. An AvailableValue is @@ -217,6 +244,7 @@ struct llvm::gvn::AvailableValueInBlock { unsigned Offset = 0) { return get(BB, AvailableValue::get(V, Offset)); } + static AvailableValueInBlock getUndef(BasicBlock *BB) { return get(BB, AvailableValue::getUndef()); } @@ -344,7 +372,7 @@ GVN::Expression GVN::ValueTable::createExtractvalueExpr(ExtractValueInst *EI) { // ValueTable External Functions //===----------------------------------------------------------------------===// -GVN::ValueTable::ValueTable() : nextValueNumber(1) {} +GVN::ValueTable::ValueTable() = default; GVN::ValueTable::ValueTable(const ValueTable &) = default; GVN::ValueTable::ValueTable(ValueTable &&) = default; GVN::ValueTable::~ValueTable() = default; @@ -456,7 +484,6 @@ uint32_t GVN::ValueTable::lookupOrAddCall(CallInst *C) { uint32_t v = lookupOrAdd(cdep); valueNumbering[C] = v; return v; - } else { valueNumbering[C] = nextValueNumber; return nextValueNumber++; @@ -710,9 +737,6 @@ SpeculationFailure: return false; } - - - /// Given a set of loads specified by ValuesPerBlock, /// construct SSA form, allowing us to eliminate LI. This returns the value /// that should be used at LI's definition site. @@ -806,6 +830,7 @@ static void reportMayClobberedLoad(LoadInst *LI, MemDepResult DepInfo, DominatorTree *DT, OptimizationRemarkEmitter *ORE) { using namespace ore; + User *OtherAccess = nullptr; OptimizationRemarkMissed R(DEBUG_TYPE, "LoadClobbered", LI); @@ -834,7 +859,6 @@ static void reportMayClobberedLoad(LoadInst *LI, MemDepResult DepInfo, bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, Value *Address, AvailableValue &Res) { - assert((DepInfo.isDef() || DepInfo.isClobber()) && "expected a local dependence"); assert(LI->isUnordered() && "rules below are incorrect for ordered access"); @@ -966,7 +990,6 @@ bool GVN::AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo, void GVN::AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps, AvailValInBlkVect &ValuesPerBlock, UnavailBlkVect &UnavailableBlocks) { - // Filter out useless results (non-locals, etc). Keep track of the blocks // where we have a value available in repl, also keep track of whether we see // dependencies that produce an unknown value for the load (such as a call @@ -1232,6 +1255,7 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock, static void reportLoadElim(LoadInst *LI, Value *AvailableValue, OptimizationRemarkEmitter *ORE) { using namespace ore; + ORE->emit(OptimizationRemark(DEBUG_TYPE, "LoadElim", LI) << "load of type " << NV("Type", LI->getType()) << " eliminated" << setExtraArgs() << " in favor of " @@ -1613,7 +1637,6 @@ static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, return Pred != nullptr; } - void GVN::assignBlockRPONumber(Function &F) { uint32_t NextBlockNumber = 1; ReversePostOrderTraversal RPOT(&F); @@ -1621,7 +1644,6 @@ void GVN::assignBlockRPONumber(Function &F) { BlockRPONumber[BB] = NextBlockNumber++; } - // Tries to replace instruction with const, using information from // ReplaceWithConstMap. bool GVN::replaceOperandsWithConsts(Instruction *Instr) const { @@ -2145,7 +2167,7 @@ bool GVN::performScalarPRE(Instruction *CurInst) { // when CurInst has operand defined in CurrentBlock (so it may be defined // by phi in the loop header). if (BlockRPONumber[P] >= BlockRPONumber[CurrentBlock] && - any_of(CurInst->operands(), [&](const Use &U) { + llvm::any_of(CurInst->operands(), [&](const Use &U) { if (auto *Inst = dyn_cast(U.get())) return Inst->getParent() == CurrentBlock; return false; @@ -2205,7 +2227,7 @@ bool GVN::performScalarPRE(Instruction *CurInst) { // Either we should have filled in the PRE instruction, or we should // not have needed insertions. - assert (PREInstr != nullptr || NumWithout == 0); + assert(PREInstr != nullptr || NumWithout == 0); ++NumGVNPRE; @@ -2461,6 +2483,7 @@ void GVN::assignValNumForDeadCode() { class llvm::gvn::GVNLegacyPass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid + explicit GVNLegacyPass(bool NoLoads = false) : FunctionPass(ID), NoLoads(NoLoads) { initializeGVNLegacyPassPass(*PassRegistry::getPassRegistry()); @@ -2504,11 +2527,6 @@ private: char GVNLegacyPass::ID = 0; -// The public interface to this file... -FunctionPass *llvm::createGVNPass(bool NoLoads) { - return new GVNLegacyPass(NoLoads); -} - INITIALIZE_PASS_BEGIN(GVNLegacyPass, "gvn", "Global Value Numbering", false, false) INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass) @@ -2518,3 +2536,8 @@ INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass) INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) INITIALIZE_PASS_END(GVNLegacyPass, "gvn", "Global Value Numbering", false, false) + +// The public interface to this file... +FunctionPass *llvm::createGVNPass(bool NoLoads) { + return new GVNLegacyPass(NoLoads); +} diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index 930ae328ad71..33afc207a959 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -14,25 +14,50 @@ #include "llvm/Transforms/Scalar/JumpThreading.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/BlockFrequencyInfoImpl.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InstructionSimplify.h" +#include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Value.h" #include "llvm/Pass.h" +#include "llvm/Support/BlockFrequency.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -41,8 +66,15 @@ #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/SSAUpdater.h" +#include "llvm/Transforms/Utils/ValueMapper.h" #include +#include +#include +#include +#include #include +#include + using namespace llvm; using namespace jumpthreading; @@ -70,6 +102,7 @@ static cl::opt PrintLVIAfterJumpThreading( cl::Hidden); namespace { + /// This pass performs 'jump threading', which looks at blocks that have /// multiple predecessors and multiple successors. If one or more of the /// predecessors of the block can be proven to always jump to one of the @@ -85,12 +118,12 @@ namespace { /// /// In this case, the unconditional branch at the end of the first if can be /// revectored to the false side of the second if. - /// class JumpThreading : public FunctionPass { JumpThreadingPass Impl; public: static char ID; // Pass identification + JumpThreading(int T = -1) : FunctionPass(ID), Impl(T) { initializeJumpThreadingPass(*PassRegistry::getPassRegistry()); } @@ -108,9 +141,11 @@ namespace { void releaseMemory() override { Impl.releaseMemory(); } }; -} + +} // end anonymous namespace char JumpThreading::ID = 0; + INITIALIZE_PASS_BEGIN(JumpThreading, "jump-threading", "Jump Threading", false, false) INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass) @@ -120,7 +155,9 @@ INITIALIZE_PASS_END(JumpThreading, "jump-threading", "Jump Threading", false, false) // Public interface to the Jump Threading pass -FunctionPass *llvm::createJumpThreadingPass(int Threshold) { return new JumpThreading(Threshold); } +FunctionPass *llvm::createJumpThreadingPass(int Threshold) { + return new JumpThreading(Threshold); +} JumpThreadingPass::JumpThreadingPass(int T) { BBDupThreshold = (T == -1) ? BBDuplicateThreshold : unsigned(T); @@ -177,7 +214,7 @@ static void updatePredecessorProfileMetadata(PHINode *PN, BasicBlock *BB) { BasicBlock *PhiBB) -> std::pair { auto *PredBB = IncomingBB; auto *SuccBB = PhiBB; - for (;;) { + while (true) { BranchInst *PredBr = dyn_cast(PredBB->getTerminator()); if (PredBr && PredBr->isConditional()) return {PredBB, SuccBB}; @@ -236,7 +273,6 @@ static void updatePredecessorProfileMetadata(PHINode *PN, BasicBlock *BB) { } /// runOnFunction - Toplevel algorithm. -/// bool JumpThreading::runOnFunction(Function &F) { if (skipFunction(F)) return false; @@ -264,7 +300,6 @@ bool JumpThreading::runOnFunction(Function &F) { PreservedAnalyses JumpThreadingPass::run(Function &F, FunctionAnalysisManager &AM) { - auto &TLI = AM.getResult(F); auto &LVI = AM.getResult(F); auto &AA = AM.getResult(F); @@ -293,7 +328,6 @@ bool JumpThreadingPass::runImpl(Function &F, TargetLibraryInfo *TLI_, bool HasProfileData_, std::unique_ptr BFI_, std::unique_ptr BPI_) { - DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n"); TLI = TLI_; LVI = LVI_; @@ -493,7 +527,6 @@ static unsigned getJumpThreadDuplicationCost(BasicBlock *BB, /// within the loop (forming a nested loop). This simple analysis is not rich /// enough to track all of these properties and keep it up-to-date as the CFG /// mutates, so we don't allow any of these transformations. -/// void JumpThreadingPass::FindLoopHeaders(Function &F) { SmallVector, 32> Edges; FindFunctionBackedges(F, Edges); @@ -527,7 +560,6 @@ static Constant *getKnownConstant(Value *Val, ConstantPreference Preference) { /// BB in the result vector. /// /// This returns true if there were any known values. -/// bool JumpThreadingPass::ComputeValueKnownInPredecessors( Value *V, BasicBlock *BB, PredValueInfo &Result, ConstantPreference Preference, Instruction *CxtI) { @@ -764,6 +796,7 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors( // x as a live-in. { using namespace PatternMatch; + Value *AddLHS; ConstantInt *AddConst; if (isa(CmpConst) && @@ -860,14 +893,11 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors( return !Result.empty(); } - - /// GetBestDestForBranchOnUndef - If we determine that the specified block ends /// in an undefined jump, decide which block is best to revector to. /// /// Since we can pick an arbitrary destination, we pick the successor with the /// fewest predecessors. This should reduce the in-degree of the others. -/// static unsigned GetBestDestForJumpOnUndef(BasicBlock *BB) { TerminatorInst *BBTerm = BB->getTerminator(); unsigned MinSucc = 0; @@ -1088,7 +1118,6 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) { // for loads that are used by a switch or by the condition for the branch. If // we see one, check to see if it's partially redundant. If so, insert a PHI // which can then be used to thread the values. - // Value *SimplifyValue = CondInst; if (CmpInst *CondCmp = dyn_cast(SimplifyValue)) if (isa(CondCmp->getOperand(1))) @@ -1108,7 +1137,6 @@ bool JumpThreadingPass::ProcessBlock(BasicBlock *BB) { // Handle a variety of cases where we are branching on something derived from // a PHI node in the current block. If we can prove that any predecessors // compute a predictable value based on a PHI node, thread those predecessors. - // if (ProcessThreadableEdges(CondInst, BB, Preference, Terminator)) return true; @@ -1238,7 +1266,9 @@ bool JumpThreadingPass::SimplifyPartiallyRedundantLoad(LoadInst *LI) { LI->getAAMetadata(AATags); SmallPtrSet PredsScanned; - typedef SmallVector, 8> AvailablePredsTy; + + using AvailablePredsTy = SmallVector, 8>; + AvailablePredsTy AvailablePreds; BasicBlock *OneUnavailablePred = nullptr; SmallVector CSELoads; @@ -1397,8 +1427,8 @@ bool JumpThreadingPass::SimplifyPartiallyRedundantLoad(LoadInst *LI) { /// the list. static BasicBlock * FindMostPopularDest(BasicBlock *BB, - const SmallVectorImpl > &PredToDestList) { + const SmallVectorImpl> &PredToDestList) { assert(!PredToDestList.empty()); // Determine popularity. If there are multiple possible destinations, we @@ -1616,7 +1646,6 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB, /// ProcessBranchOnPHI - We have an otherwise unthreadable conditional branch on /// a PHI node in the current block. See if there are any simplifications we /// can do based on inputs to the phi node. -/// bool JumpThreadingPass::ProcessBranchOnPHI(PHINode *PN) { BasicBlock *BB = PN->getParent(); @@ -1646,7 +1675,6 @@ bool JumpThreadingPass::ProcessBranchOnPHI(PHINode *PN) { /// ProcessBranchOnXOR - We have an otherwise unthreadable conditional branch on /// a xor instruction in the current block. See if there are any /// simplifications we can do based on inputs to the xor. -/// bool JumpThreadingPass::ProcessBranchOnXOR(BinaryOperator *BO) { BasicBlock *BB = BO->getParent(); @@ -1751,7 +1779,6 @@ bool JumpThreadingPass::ProcessBranchOnXOR(BinaryOperator *BO) { return DuplicateCondBranchOnPHIIntoPred(BB, BlocksToFoldInto); } - /// AddPHINodeEntriesForMappedBlock - We're adding 'NewPred' as a new /// predecessor to the PHIBB block. If it has PHI nodes, add entries for /// NewPred using the entries from OldPred (suitably mapped). @@ -1914,7 +1941,6 @@ bool JumpThreadingPass::ThreadEdge(BasicBlock *BB, DEBUG(dbgs() << "\n"); } - // Ok, NewBB is good to go. Update the terminator of PredBB to jump to // NewBB instead of BB. This eliminates predecessors from BB, which requires // us to simplify any PHI nodes in BB. @@ -2313,7 +2339,7 @@ bool JumpThreadingPass::TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB) { /// %p = phi [0, %bb1], [1, %bb2], [0, %bb3], [1, %bb4], ... /// %c = cmp %p, 0 /// %s = select %c, trueval, falseval -// +/// /// And expand the select into a branch structure. This later enables /// jump-threading over bb in this pass. /// @@ -2399,6 +2425,7 @@ bool JumpThreadingPass::TryToUnfoldSelectInCurrBB(BasicBlock *BB) { /// guard is then threaded to one of them. bool JumpThreadingPass::ProcessGuards(BasicBlock *BB) { using namespace PatternMatch; + // We only want to deal with two predecessors. BasicBlock *Pred1, *Pred2; auto PI = pred_begin(BB), PE = pred_end(BB);