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