mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-07 13:09:52 +00:00
[gvn] Reformat a chunk of the GVN code that is strangely indented prior
to restructuring it for porting to the new pass manager. No functionality changed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263083 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c5266b5293
commit
61c136c43e
@ -511,272 +511,271 @@ void ValueTable::verifyRemoved(const Value *V) const {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class GVN;
|
class GVN;
|
||||||
/// Represents a particular available value that we know how to materialize.
|
|
||||||
/// Materialization of an AvailableValue never fails. An AvailableValue is
|
|
||||||
/// implicitly associated with a rematerialization point which is the
|
|
||||||
/// location of the instruction from which it was formed.
|
|
||||||
struct AvailableValue {
|
|
||||||
enum ValType {
|
|
||||||
SimpleVal, // A simple offsetted value that is accessed.
|
|
||||||
LoadVal, // A value produced by a load.
|
|
||||||
MemIntrin, // A memory intrinsic which is loaded from.
|
|
||||||
UndefVal // A UndefValue representing a value from dead block (which
|
|
||||||
// is not yet physically removed from the CFG).
|
|
||||||
};
|
|
||||||
|
|
||||||
/// V - The value that is live out of the block.
|
|
||||||
PointerIntPair<Value *, 2, ValType> Val;
|
|
||||||
|
|
||||||
/// Offset - The byte offset in Val that is interesting for the load query.
|
|
||||||
unsigned Offset;
|
|
||||||
|
|
||||||
static AvailableValue get(Value *V,
|
|
||||||
unsigned Offset = 0) {
|
|
||||||
AvailableValue Res;
|
|
||||||
Res.Val.setPointer(V);
|
|
||||||
Res.Val.setInt(SimpleVal);
|
|
||||||
Res.Offset = Offset;
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AvailableValue getMI(MemIntrinsic *MI,
|
|
||||||
unsigned Offset = 0) {
|
|
||||||
AvailableValue Res;
|
|
||||||
Res.Val.setPointer(MI);
|
|
||||||
Res.Val.setInt(MemIntrin);
|
|
||||||
Res.Offset = Offset;
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AvailableValue getLoad(LoadInst *LI,
|
|
||||||
unsigned Offset = 0) {
|
|
||||||
AvailableValue Res;
|
|
||||||
Res.Val.setPointer(LI);
|
|
||||||
Res.Val.setInt(LoadVal);
|
|
||||||
Res.Offset = Offset;
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static AvailableValue getUndef() {
|
/// Represents a particular available value that we know how to materialize.
|
||||||
AvailableValue Res;
|
/// Materialization of an AvailableValue never fails. An AvailableValue is
|
||||||
Res.Val.setPointer(nullptr);
|
/// implicitly associated with a rematerialization point which is the
|
||||||
Res.Val.setInt(UndefVal);
|
/// location of the instruction from which it was formed.
|
||||||
Res.Offset = 0;
|
struct AvailableValue {
|
||||||
return Res;
|
enum ValType {
|
||||||
}
|
SimpleVal, // A simple offsetted value that is accessed.
|
||||||
|
LoadVal, // A value produced by a load.
|
||||||
bool isSimpleValue() const { return Val.getInt() == SimpleVal; }
|
MemIntrin, // A memory intrinsic which is loaded from.
|
||||||
bool isCoercedLoadValue() const { return Val.getInt() == LoadVal; }
|
UndefVal // A UndefValue representing a value from dead block (which
|
||||||
bool isMemIntrinValue() const { return Val.getInt() == MemIntrin; }
|
// is not yet physically removed from the CFG).
|
||||||
bool isUndefValue() const { return Val.getInt() == UndefVal; }
|
|
||||||
|
|
||||||
Value *getSimpleValue() const {
|
|
||||||
assert(isSimpleValue() && "Wrong accessor");
|
|
||||||
return Val.getPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadInst *getCoercedLoadValue() const {
|
|
||||||
assert(isCoercedLoadValue() && "Wrong accessor");
|
|
||||||
return cast<LoadInst>(Val.getPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
MemIntrinsic *getMemIntrinValue() const {
|
|
||||||
assert(isMemIntrinValue() && "Wrong accessor");
|
|
||||||
return cast<MemIntrinsic>(Val.getPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emit code at the specified insertion point to adjust the value defined
|
|
||||||
/// here to the specified type. This handles various coercion cases.
|
|
||||||
Value *MaterializeAdjustedValue(LoadInst *LI, Instruction *InsertPt,
|
|
||||||
GVN &gvn) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents an AvailableValue which can be rematerialized at the end of
|
/// V - The value that is live out of the block.
|
||||||
/// the associated BasicBlock.
|
PointerIntPair<Value *, 2, ValType> Val;
|
||||||
struct AvailableValueInBlock {
|
|
||||||
/// BB - The basic block in question.
|
|
||||||
BasicBlock *BB;
|
|
||||||
|
|
||||||
/// AV - The actual available value
|
/// Offset - The byte offset in Val that is interesting for the load query.
|
||||||
AvailableValue AV;
|
unsigned Offset;
|
||||||
|
|
||||||
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV) {
|
static AvailableValue get(Value *V, unsigned Offset = 0) {
|
||||||
AvailableValueInBlock Res;
|
AvailableValue Res;
|
||||||
Res.BB = BB;
|
Res.Val.setPointer(V);
|
||||||
Res.AV = std::move(AV);
|
Res.Val.setInt(SimpleVal);
|
||||||
return Res;
|
Res.Offset = Offset;
|
||||||
}
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
|
static AvailableValue getMI(MemIntrinsic *MI, unsigned Offset = 0) {
|
||||||
unsigned Offset = 0) {
|
AvailableValue Res;
|
||||||
return get(BB, AvailableValue::get(V, Offset));
|
Res.Val.setPointer(MI);
|
||||||
}
|
Res.Val.setInt(MemIntrin);
|
||||||
static AvailableValueInBlock getUndef(BasicBlock *BB) {
|
Res.Offset = Offset;
|
||||||
return get(BB, AvailableValue::getUndef());
|
return Res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit code at the end of this block to adjust the value defined here to
|
static AvailableValue getLoad(LoadInst *LI, unsigned Offset = 0) {
|
||||||
/// the specified type. This handles various coercion cases.
|
AvailableValue Res;
|
||||||
Value *MaterializeAdjustedValue(LoadInst *LI, GVN &gvn) const {
|
Res.Val.setPointer(LI);
|
||||||
return AV.MaterializeAdjustedValue(LI, BB->getTerminator(), gvn);
|
Res.Val.setInt(LoadVal);
|
||||||
}
|
Res.Offset = Offset;
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AvailableValue getUndef() {
|
||||||
|
AvailableValue Res;
|
||||||
|
Res.Val.setPointer(nullptr);
|
||||||
|
Res.Val.setInt(UndefVal);
|
||||||
|
Res.Offset = 0;
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSimpleValue() const { return Val.getInt() == SimpleVal; }
|
||||||
|
bool isCoercedLoadValue() const { return Val.getInt() == LoadVal; }
|
||||||
|
bool isMemIntrinValue() const { return Val.getInt() == MemIntrin; }
|
||||||
|
bool isUndefValue() const { return Val.getInt() == UndefVal; }
|
||||||
|
|
||||||
|
Value *getSimpleValue() const {
|
||||||
|
assert(isSimpleValue() && "Wrong accessor");
|
||||||
|
return Val.getPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadInst *getCoercedLoadValue() const {
|
||||||
|
assert(isCoercedLoadValue() && "Wrong accessor");
|
||||||
|
return cast<LoadInst>(Val.getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
MemIntrinsic *getMemIntrinValue() const {
|
||||||
|
assert(isMemIntrinValue() && "Wrong accessor");
|
||||||
|
return cast<MemIntrinsic>(Val.getPointer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emit code at the specified insertion point to adjust the value defined
|
||||||
|
/// here to the specified type. This handles various coercion cases.
|
||||||
|
Value *MaterializeAdjustedValue(LoadInst *LI, Instruction *InsertPt,
|
||||||
|
GVN &gvn) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Represents an AvailableValue which can be rematerialized at the end of
|
||||||
|
/// the associated BasicBlock.
|
||||||
|
struct AvailableValueInBlock {
|
||||||
|
/// BB - The basic block in question.
|
||||||
|
BasicBlock *BB;
|
||||||
|
|
||||||
|
/// AV - The actual available value
|
||||||
|
AvailableValue AV;
|
||||||
|
|
||||||
|
static AvailableValueInBlock get(BasicBlock *BB, AvailableValue &&AV) {
|
||||||
|
AvailableValueInBlock Res;
|
||||||
|
Res.BB = BB;
|
||||||
|
Res.AV = std::move(AV);
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AvailableValueInBlock get(BasicBlock *BB, Value *V,
|
||||||
|
unsigned Offset = 0) {
|
||||||
|
return get(BB, AvailableValue::get(V, Offset));
|
||||||
|
}
|
||||||
|
static AvailableValueInBlock getUndef(BasicBlock *BB) {
|
||||||
|
return get(BB, AvailableValue::getUndef());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emit code at the end of this block to adjust the value defined here to
|
||||||
|
/// the specified type. This handles various coercion cases.
|
||||||
|
Value *MaterializeAdjustedValue(LoadInst *LI, GVN &gvn) const {
|
||||||
|
return AV.MaterializeAdjustedValue(LI, BB->getTerminator(), gvn);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GVN : public FunctionPass {
|
||||||
|
bool NoLoads;
|
||||||
|
MemoryDependenceResults *MD;
|
||||||
|
DominatorTree *DT;
|
||||||
|
const TargetLibraryInfo *TLI;
|
||||||
|
AssumptionCache *AC;
|
||||||
|
SetVector<BasicBlock *> DeadBlocks;
|
||||||
|
|
||||||
|
ValueTable VN;
|
||||||
|
|
||||||
|
/// A mapping from value numbers to lists of Value*'s that
|
||||||
|
/// have that value number. Use findLeader to query it.
|
||||||
|
struct LeaderTableEntry {
|
||||||
|
Value *Val;
|
||||||
|
const BasicBlock *BB;
|
||||||
|
LeaderTableEntry *Next;
|
||||||
};
|
};
|
||||||
|
DenseMap<uint32_t, LeaderTableEntry> LeaderTable;
|
||||||
|
BumpPtrAllocator TableAllocator;
|
||||||
|
|
||||||
class GVN : public FunctionPass {
|
// Block-local map of equivalent values to their leader, does not
|
||||||
bool NoLoads;
|
// propagate to any successors. Entries added mid-block are applied
|
||||||
MemoryDependenceResults *MD;
|
// to the remaining instructions in the block.
|
||||||
DominatorTree *DT;
|
SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
|
||||||
const TargetLibraryInfo *TLI;
|
SmallVector<Instruction *, 8> InstrsToErase;
|
||||||
AssumptionCache *AC;
|
|
||||||
SetVector<BasicBlock *> DeadBlocks;
|
|
||||||
|
|
||||||
ValueTable VN;
|
typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
|
||||||
|
typedef SmallVector<AvailableValueInBlock, 64> AvailValInBlkVect;
|
||||||
|
typedef SmallVector<BasicBlock *, 64> UnavailBlkVect;
|
||||||
|
|
||||||
/// A mapping from value numbers to lists of Value*'s that
|
public:
|
||||||
/// have that value number. Use findLeader to query it.
|
static char ID; // Pass identification, replacement for typeid
|
||||||
struct LeaderTableEntry {
|
explicit GVN(bool noloads = false)
|
||||||
Value *Val;
|
: FunctionPass(ID), NoLoads(noloads), MD(nullptr) {
|
||||||
const BasicBlock *BB;
|
initializeGVNPass(*PassRegistry::getPassRegistry());
|
||||||
LeaderTableEntry *Next;
|
}
|
||||||
};
|
|
||||||
DenseMap<uint32_t, LeaderTableEntry> LeaderTable;
|
|
||||||
BumpPtrAllocator TableAllocator;
|
|
||||||
|
|
||||||
// Block-local map of equivalent values to their leader, does not
|
bool runOnFunction(Function &F) override;
|
||||||
// propagate to any successors. Entries added mid-block are applied
|
|
||||||
// to the remaining instructions in the block.
|
|
||||||
SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
|
|
||||||
SmallVector<Instruction*, 8> InstrsToErase;
|
|
||||||
|
|
||||||
typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
|
/// This removes the specified instruction from
|
||||||
typedef SmallVector<AvailableValueInBlock, 64> AvailValInBlkVect;
|
/// our various maps and marks it for deletion.
|
||||||
typedef SmallVector<BasicBlock*, 64> UnavailBlkVect;
|
void markInstructionForDeletion(Instruction *I) {
|
||||||
|
VN.erase(I);
|
||||||
|
InstrsToErase.push_back(I);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
DominatorTree &getDominatorTree() const { return *DT; }
|
||||||
static char ID; // Pass identification, replacement for typeid
|
AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
|
||||||
explicit GVN(bool noloads = false)
|
MemoryDependenceResults &getMemDep() const { return *MD; }
|
||||||
: FunctionPass(ID), NoLoads(noloads), MD(nullptr) {
|
|
||||||
initializeGVNPass(*PassRegistry::getPassRegistry());
|
private:
|
||||||
|
/// Push a new Value to the LeaderTable onto the list for its value number.
|
||||||
|
void addToLeaderTable(uint32_t N, Value *V, const BasicBlock *BB) {
|
||||||
|
LeaderTableEntry &Curr = LeaderTable[N];
|
||||||
|
if (!Curr.Val) {
|
||||||
|
Curr.Val = V;
|
||||||
|
Curr.BB = BB;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnFunction(Function &F) override;
|
LeaderTableEntry *Node = TableAllocator.Allocate<LeaderTableEntry>();
|
||||||
|
Node->Val = V;
|
||||||
|
Node->BB = BB;
|
||||||
|
Node->Next = Curr.Next;
|
||||||
|
Curr.Next = Node;
|
||||||
|
}
|
||||||
|
|
||||||
/// This removes the specified instruction from
|
/// Scan the list of values corresponding to a given
|
||||||
/// our various maps and marks it for deletion.
|
/// value number, and remove the given instruction if encountered.
|
||||||
void markInstructionForDeletion(Instruction *I) {
|
void removeFromLeaderTable(uint32_t N, Instruction *I, BasicBlock *BB) {
|
||||||
VN.erase(I);
|
LeaderTableEntry *Prev = nullptr;
|
||||||
InstrsToErase.push_back(I);
|
LeaderTableEntry *Curr = &LeaderTable[N];
|
||||||
|
|
||||||
|
while (Curr && (Curr->Val != I || Curr->BB != BB)) {
|
||||||
|
Prev = Curr;
|
||||||
|
Curr = Curr->Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
DominatorTree &getDominatorTree() const { return *DT; }
|
if (!Curr)
|
||||||
AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
|
return;
|
||||||
MemoryDependenceResults &getMemDep() const { return *MD; }
|
|
||||||
private:
|
|
||||||
/// Push a new Value to the LeaderTable onto the list for its value number.
|
|
||||||
void addToLeaderTable(uint32_t N, Value *V, const BasicBlock *BB) {
|
|
||||||
LeaderTableEntry &Curr = LeaderTable[N];
|
|
||||||
if (!Curr.Val) {
|
|
||||||
Curr.Val = V;
|
|
||||||
Curr.BB = BB;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LeaderTableEntry *Node = TableAllocator.Allocate<LeaderTableEntry>();
|
if (Prev) {
|
||||||
Node->Val = V;
|
Prev->Next = Curr->Next;
|
||||||
Node->BB = BB;
|
} else {
|
||||||
Node->Next = Curr.Next;
|
if (!Curr->Next) {
|
||||||
Curr.Next = Node;
|
Curr->Val = nullptr;
|
||||||
}
|
Curr->BB = nullptr;
|
||||||
|
|
||||||
/// Scan the list of values corresponding to a given
|
|
||||||
/// value number, and remove the given instruction if encountered.
|
|
||||||
void removeFromLeaderTable(uint32_t N, Instruction *I, BasicBlock *BB) {
|
|
||||||
LeaderTableEntry* Prev = nullptr;
|
|
||||||
LeaderTableEntry* Curr = &LeaderTable[N];
|
|
||||||
|
|
||||||
while (Curr && (Curr->Val != I || Curr->BB != BB)) {
|
|
||||||
Prev = Curr;
|
|
||||||
Curr = Curr->Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Curr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Prev) {
|
|
||||||
Prev->Next = Curr->Next;
|
|
||||||
} else {
|
} else {
|
||||||
if (!Curr->Next) {
|
LeaderTableEntry *Next = Curr->Next;
|
||||||
Curr->Val = nullptr;
|
Curr->Val = Next->Val;
|
||||||
Curr->BB = nullptr;
|
Curr->BB = Next->BB;
|
||||||
} else {
|
Curr->Next = Next->Next;
|
||||||
LeaderTableEntry* Next = Curr->Next;
|
|
||||||
Curr->Val = Next->Val;
|
|
||||||
Curr->BB = Next->BB;
|
|
||||||
Curr->Next = Next->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// List of critical edges to be split between iterations.
|
// List of critical edges to be split between iterations.
|
||||||
SmallVector<std::pair<TerminatorInst*, unsigned>, 4> toSplit;
|
SmallVector<std::pair<TerminatorInst *, unsigned>, 4> toSplit;
|
||||||
|
|
||||||
// This transformation requires dominator postdominator info
|
// This transformation requires dominator postdominator info
|
||||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||||
AU.addRequired<AssumptionCacheTracker>();
|
AU.addRequired<AssumptionCacheTracker>();
|
||||||
AU.addRequired<DominatorTreeWrapperPass>();
|
AU.addRequired<DominatorTreeWrapperPass>();
|
||||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||||
if (!NoLoads)
|
if (!NoLoads)
|
||||||
AU.addRequired<MemoryDependenceWrapperPass>();
|
AU.addRequired<MemoryDependenceWrapperPass>();
|
||||||
AU.addRequired<AAResultsWrapperPass>();
|
AU.addRequired<AAResultsWrapperPass>();
|
||||||
|
|
||||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper functions of redundant load elimination
|
||||||
|
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, 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);
|
||||||
|
|
||||||
// Helper functions of redundant load elimination
|
// Other helper routines
|
||||||
bool processLoad(LoadInst *L);
|
bool processInstruction(Instruction *I);
|
||||||
bool processNonLocalLoad(LoadInst *L);
|
bool processBlock(BasicBlock *BB);
|
||||||
bool processAssumeIntrinsic(IntrinsicInst *II);
|
void dump(DenseMap<uint32_t, Value *> &d);
|
||||||
/// Given a local dependency (Def or Clobber) determine if a value is
|
bool iterateOnFunction(Function &F);
|
||||||
/// available for the load. Returns true if an value is known to be
|
bool performPRE(Function &F);
|
||||||
/// available and populates Res. Returns false otherwise.
|
bool performScalarPRE(Instruction *I);
|
||||||
bool AnalyzeLoadAvailability(LoadInst *LI, MemDepResult DepInfo,
|
bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
||||||
Value *Address, AvailableValue &Res);
|
unsigned int ValNo);
|
||||||
/// Given a list of non-local dependencies, determine if a value is
|
Value *findLeader(const BasicBlock *BB, uint32_t num);
|
||||||
/// available for the load in each specified block. If it is, add it to
|
void cleanupGlobalSets();
|
||||||
/// ValuesPerBlock. If not, add it to UnavailableBlocks.
|
void verifyRemoved(const Instruction *I) const;
|
||||||
void AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
|
bool splitCriticalEdges();
|
||||||
AvailValInBlkVect &ValuesPerBlock,
|
BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);
|
||||||
UnavailBlkVect &UnavailableBlocks);
|
bool replaceOperandsWithConsts(Instruction *I) const;
|
||||||
bool PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
|
bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root,
|
||||||
UnavailBlkVect &UnavailableBlocks);
|
bool DominatesByEdge);
|
||||||
|
bool processFoldableCondBr(BranchInst *BI);
|
||||||
|
void addDeadBlock(BasicBlock *BB);
|
||||||
|
void assignValNumForDeadCode();
|
||||||
|
};
|
||||||
|
|
||||||
// Other helper routines
|
char GVN::ID = 0;
|
||||||
bool processInstruction(Instruction *I);
|
|
||||||
bool processBlock(BasicBlock *BB);
|
|
||||||
void dump(DenseMap<uint32_t, Value*> &d);
|
|
||||||
bool iterateOnFunction(Function &F);
|
|
||||||
bool performPRE(Function &F);
|
|
||||||
bool performScalarPRE(Instruction *I);
|
|
||||||
bool performScalarPREInsertion(Instruction *Instr, BasicBlock *Pred,
|
|
||||||
unsigned int ValNo);
|
|
||||||
Value *findLeader(const BasicBlock *BB, uint32_t num);
|
|
||||||
void cleanupGlobalSets();
|
|
||||||
void verifyRemoved(const Instruction *I) const;
|
|
||||||
bool splitCriticalEdges();
|
|
||||||
BasicBlock *splitCriticalEdges(BasicBlock *Pred, BasicBlock *Succ);
|
|
||||||
bool replaceOperandsWithConsts(Instruction *I) const;
|
|
||||||
bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root,
|
|
||||||
bool DominatesByEdge);
|
|
||||||
bool processFoldableCondBr(BranchInst *BI);
|
|
||||||
void addDeadBlock(BasicBlock *BB);
|
|
||||||
void assignValNumForDeadCode();
|
|
||||||
};
|
|
||||||
|
|
||||||
char GVN::ID = 0;
|
} // End anonymous namespace.
|
||||||
}
|
|
||||||
|
|
||||||
// The public interface to this file...
|
// The public interface to this file...
|
||||||
FunctionPass *llvm::createGVNPass(bool NoLoads) {
|
FunctionPass *llvm::createGVNPass(bool NoLoads) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user