[llvm] r263208 - [PM] Port GVN to the new pass manager, wire it up, and teach a couple of
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 7 10:37:00 PDT 2016
Chandler Carruth via llvm-commits <llvm-commits at lists.llvm.org> writes:
> Author: chandlerc
> Date: Fri Mar 11 02:50:55 2016
> New Revision: 263208
>
> URL: http://llvm.org/viewvc/llvm-project?rev=263208&view=rev
> Log:
> [PM] Port GVN to the new pass manager, wire it up, and teach a couple of
> tests to run GVN in both modes.
>
> This is mostly the boring refactoring just like SROA and other complex
> transformation passes. There is some trickiness in that GVN's
> ValueNumber class requires hand holding to get to compile cleanly. I'm
> open to suggestions about a better pattern there, but I tried several
> before settling on this. I was trying to balance my desire to sink as
> much implementation detail into the source file as possible without
> introducing overly many layers of abstraction.
>
> Much like with SROA, the design of this system is made somewhat more
> cumbersome by the need to support both pass managers without duplicating
> the significant state and logic of the pass. The same compromise is
> struck here.
>
> I've also left a FIXME in a doxygen comment as the GVN pass seems to
> have pretty woeful documentation within it. I'd like to submit this with
> the FIXME and let those more deeply familiar backfill the information
> here now that we have a nice place in an interface to put that kind of
> documentaiton.
Some drive by comments about some cleanups we should probably do in code
that you moved. The problems were already there, though ;)
> Differential Revision: http://reviews.llvm.org/D18019
>
> Added:
> llvm/trunk/include/llvm/Transforms/Scalar/GVN.h
> Modified:
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/include/llvm/LinkAllPasses.h
> llvm/trunk/include/llvm/Transforms/Scalar.h
> llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
> llvm/trunk/lib/Passes/PassBuilder.cpp
> llvm/trunk/lib/Passes/PassRegistry.def
> llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp
> llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
> llvm/trunk/lib/Transforms/Scalar/GVN.cpp
> llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
> llvm/trunk/test/Transforms/GVN/basic.ll
> llvm/trunk/test/Transforms/GVN/pre-gep-load.ll
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Fri Mar 11 02:50:55 2016
> @@ -138,7 +138,7 @@ void initializeExpandISelPseudosPass(Pas
> void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&);
> void initializeGCMachineCodeAnalysisPass(PassRegistry&);
> void initializeGCModuleInfoPass(PassRegistry&);
> -void initializeGVNPass(PassRegistry&);
> +void initializeGVNLegacyPassPass(PassRegistry&);
> void initializeGlobalDCEPass(PassRegistry&);
> void initializeGlobalOptPass(PassRegistry&);
> void initializeGlobalsAAWrapperPassPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Fri Mar 11 02:50:55 2016
> @@ -42,6 +42,7 @@
> #include "llvm/Transforms/Instrumentation.h"
> #include "llvm/Transforms/ObjCARC.h"
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
> #include "llvm/Transforms/Utils/SymbolRewriter.h"
> #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
> #include "llvm/Transforms/Vectorize.h"
>
> Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Scalar.h Fri Mar 11 02:50:55 2016
> @@ -335,13 +335,6 @@ FunctionPass *createMergedLoadStoreMotio
>
> //===----------------------------------------------------------------------===//
> //
> -// GVN - This pass performs global value numbering and redundant load
> -// elimination cotemporaneously.
> -//
> -FunctionPass *createGVNPass(bool NoLoads = false);
> -
> -//===----------------------------------------------------------------------===//
> -//
> // MemCpyOpt - This pass performs optimizations related to eliminating memcpy
> // calls and/or combining multiple stores into memset's.
> //
>
> Added: llvm/trunk/include/llvm/Transforms/Scalar/GVN.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar/GVN.h?rev=263208&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Scalar/GVN.h (added)
> +++ llvm/trunk/include/llvm/Transforms/Scalar/GVN.h Fri Mar 11 02:50:55 2016
> @@ -0,0 +1,232 @@
> +//===- GVN.h - Eliminate redundant values and loads -------------*- C++ -*-===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +/// \file
> +/// This file provides the interface for LLVM's Global Value Numbering pass
> +/// which eliminates fully redundant instructions. It also does somewhat Ad-Hoc
> +/// PRE and dead load elimination.
> +///
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_TRANSFORMS_SCALAR_GVN_H
> +#define LLVM_TRANSFORMS_SCALAR_GVN_H
> +
> +#include "llvm/ADT/DenseMap.h"
> +#include "llvm/ADT/MapVector.h"
> +#include "llvm/ADT/SetVector.h"
> +#include "llvm/ADT/SmallPtrSet.h"
> +#include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/Analysis/AssumptionCache.h"
> +#include "llvm/Analysis/MemoryDependenceAnalysis.h"
> +#include "llvm/IR/Dominators.h"
> +#include "llvm/IR/IntrinsicInst.h"
> +#include "llvm/IR/PassManager.h"
> +
> +namespace llvm {
> +
> +/// A private "module" namespace for types and utilities used by GVN. These
> +/// are implementation details and should not be used by clients.
> +namespace gvn LLVM_LIBRARY_VISIBILITY {
> +struct AvailableValue;
> +struct AvailableValueInBlock;
> +struct Expression;
> +class GVNLegacyPass;
> +}
> +
> +/// The core GVN pass object.
> +///
> +/// FIXME: We should have a good summary of the GVN algorithm implemented by
> +/// this particular pass here.
> +class GVN : public PassBase<GVN> {
> +public:
> +
> + /// \brief Run the pass over the function.
> + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM);
> +
> + /// This removes the specified instruction from
> + /// our various maps and marks it for deletion.
> + void markInstructionForDeletion(Instruction *I) {
> + VN.erase(I);
> + InstrsToErase.push_back(I);
> + }
> +
> + DominatorTree &getDominatorTree() const { return *DT; }
> + AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
> + MemoryDependenceResults &getMemDep() const { return *MD; }
> +
> +private:
> + friend class gvn::GVNLegacyPass;
> +
> + /// This class holds the mapping between values and value numbers. It is used
> + /// as an efficient mechanism to determine the expression-wise equivalence of
> + /// two values.
> + class ValueTable {
> + DenseMap<Value *, uint32_t> valueNumbering;
> + DenseMap<gvn::Expression, uint32_t> expressionNumbering;
> + AliasAnalysis *AA;
> + MemoryDependenceResults *MD;
> + DominatorTree *DT;
> +
> + uint32_t nextValueNumber;
> +
> + gvn::Expression create_expression(Instruction *I);
> + gvn::Expression create_cmp_expression(unsigned Opcode,
> + CmpInst::Predicate Predicate,
> + Value *LHS, Value *RHS);
> + gvn::Expression create_extractvalue_expression(ExtractValueInst *EI);
> + uint32_t lookup_or_add_call(CallInst *C);
> +
> + public:
> + ValueTable();
> + ValueTable(const ValueTable &Arg);
> + ValueTable(ValueTable &&Arg);
> + ~ValueTable();
> +
> + uint32_t lookup_or_add(Value *V);
> + uint32_t lookup(Value *V) const;
> + uint32_t lookup_or_add_cmp(unsigned Opcode, CmpInst::Predicate Pred,
> + Value *LHS, Value *RHS);
These names_with_underscores are unusual in llvm - we should probably
renameThemLikeThis.
> + bool exists(Value *V) const;
> + void add(Value *V, uint32_t num);
> + void clear();
> + void erase(Value *v);
> + void setAliasAnalysis(AliasAnalysis *A) { AA = A; }
> + AliasAnalysis *getAliasAnalysis() const { return AA; }
> + void setMemDep(MemoryDependenceResults *M) { MD = M; }
> + void setDomTree(DominatorTree *D) { DT = D; }
> + uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
> + void verifyRemoved(const Value *) const;
> + };
> +
> + 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;
> +
> + // Block-local map of equivalent values to their leader, does not
> + // propagate to any successors. Entries added mid-block are applied
> + // to the remaining instructions in the block.
> + SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
> + SmallVector<Instruction *, 8> InstrsToErase;
> +
> + typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
> + typedef SmallVector<gvn::AvailableValueInBlock, 64> AvailValInBlkVect;
> + typedef SmallVector<BasicBlock *, 64> UnavailBlkVect;
> +
> + bool runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
> + const TargetLibraryInfo &RunTLI, AAResults &RunAA,
> + MemoryDependenceResults *RunMD);
> +
> + /// 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>();
> + Node->Val = V;
> + Node->BB = BB;
> + Node->Next = Curr.Next;
> + Curr.Next = Node;
> + }
> +
> + /// 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 {
> + if (!Curr->Next) {
> + Curr->Val = nullptr;
> + Curr->BB = nullptr;
> + } else {
> + LeaderTableEntry *Next = Curr->Next;
> + Curr->Val = Next->Val;
> + Curr->BB = Next->BB;
> + Curr->Next = Next->Next;
> + }
> + }
This is structured really oddly - it should at least be if/else-if
rather than an if braced inside an else block, but it'd probably be even
better to just use early returns.
> + }
> +
> + // List of critical edges to be split between iterations.
> + SmallVector<std::pair<TerminatorInst *, unsigned>, 4> toSplit;
> +
> + // 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, gvn::AvailableValue &Res);
> + /// Given a list of non-local dependencies, determine if a value is
> + /// available for the load in each specified block. If it is, add it to
> + /// ValuesPerBlock. If not, add it to UnavailableBlocks.
> + void AnalyzeLoadAvailability(LoadInst *LI, LoadDepVect &Deps,
> + AvailValInBlkVect &ValuesPerBlock,
> + UnavailBlkVect &UnavailableBlocks);
> + bool PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock,
> + UnavailBlkVect &UnavailableBlocks);
> +
> + // Other helper routines
> + 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();
> +};
> +
> +/// Create a legacy GVN pass. This also allows parameterizing whether or not
> +/// loads are eliminated by the pass.
> +FunctionPass *createGVNPass(bool NoLoads = false);
> +
> +}
> +
> +#endif
>
> Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
> +++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Fri Mar 11 02:50:55 2016
> @@ -111,7 +111,7 @@ void LTOCodeGenerator::initializeLTOPass
> initializeGlobalsAAWrapperPassPass(R);
> initializeLICMPass(R);
> initializeMergedLoadStoreMotionPass(R);
> - initializeGVNPass(R);
> + initializeGVNLegacyPassPass(R);
> initializeMemCpyOptPass(R);
> initializeDCEPass(R);
> initializeCFGSimplifyPassPass(R);
>
> Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
> +++ llvm/trunk/lib/Passes/PassBuilder.cpp Fri Mar 11 02:50:55 2016
> @@ -51,6 +51,7 @@
> #include "llvm/Transforms/Scalar/ADCE.h"
> #include "llvm/Transforms/Scalar/EarlyCSE.h"
> #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
> #include "llvm/Transforms/Scalar/SROA.h"
> #include "llvm/Transforms/Scalar/SimplifyCFG.h"
> #include <type_traits>
>
> Modified: llvm/trunk/lib/Passes/PassRegistry.def
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassRegistry.def?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Passes/PassRegistry.def (original)
> +++ llvm/trunk/lib/Passes/PassRegistry.def Fri Mar 11 02:50:55 2016
> @@ -92,6 +92,7 @@ FUNCTION_PASS("instcombine", InstCombine
> FUNCTION_PASS("invalidate<all>", InvalidateAllAnalysesPass())
> FUNCTION_PASS("no-op-function", NoOpFunctionPass())
> FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass())
> +FUNCTION_PASS("gvn", GVN())
> FUNCTION_PASS("print", PrintFunctionPass(dbgs()))
> FUNCTION_PASS("print<assumptions>", AssumptionPrinterPass(dbgs()))
> FUNCTION_PASS("print<domtree>", DominatorTreePrinterPass(dbgs()))
>
> Modified: llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp (original)
> +++ llvm/trunk/lib/Target/NVPTX/NVPTXTargetMachine.cpp Fri Mar 11 02:50:55 2016
> @@ -44,6 +44,7 @@
> #include "llvm/Target/TargetRegisterInfo.h"
> #include "llvm/Target/TargetSubtargetInfo.h"
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
>
> using namespace llvm;
>
>
> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Fri Mar 11 02:50:55 2016
> @@ -34,6 +34,7 @@
> #include "llvm/Transforms/IPO/FunctionAttrs.h"
> #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
> #include "llvm/Transforms/Vectorize.h"
> #include "llvm/Transforms/Instrumentation.h"
>
>
> Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Fri Mar 11 02:50:55 2016
> @@ -15,7 +15,7 @@
> //
> //===----------------------------------------------------------------------===//
>
> -#include "llvm/Transforms/Scalar.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
> #include "llvm/ADT/DenseMap.h"
> #include "llvm/ADT/DepthFirstIterator.h"
> #include "llvm/ADT/Hashing.h"
> @@ -53,6 +53,7 @@
> #include "llvm/Transforms/Utils/SSAUpdater.h"
> #include <vector>
> using namespace llvm;
> +using namespace llvm::gvn;
> using namespace PatternMatch;
>
> #define DEBUG_TYPE "gvn"
> @@ -74,13 +75,7 @@ static cl::opt<uint32_t>
> MaxRecurseDepth("max-recurse-depth", cl::Hidden, cl::init(1000), cl::ZeroOrMore,
> cl::desc("Max recurse depth (default = 1000)"));
>
> -//===----------------------------------------------------------------------===//
> -// ValueTable Class
> -//===----------------------------------------------------------------------===//
> -
> -namespace {
> -
> -struct Expression {
> +struct llvm::gvn::Expression {
> uint32_t opcode;
> Type *type;
> SmallVector<uint32_t, 4> varargs;
> @@ -106,45 +101,6 @@ struct Expression {
> }
> };
>
> -/// This class holds the mapping between values and value numbers. It is used
> -/// as an efficient mechanism to determine the expression-wise equivalence of
> -/// two values.
> -class ValueTable {
> - DenseMap<Value *, uint32_t> valueNumbering;
> - DenseMap<Expression, uint32_t> expressionNumbering;
> - AliasAnalysis *AA;
> - MemoryDependenceResults *MD;
> - DominatorTree *DT;
> -
> - uint32_t nextValueNumber;
> -
> - Expression create_expression(Instruction *I);
> - Expression create_cmp_expression(unsigned Opcode,
> - CmpInst::Predicate Predicate, Value *LHS,
> - Value *RHS);
> - Expression create_extractvalue_expression(ExtractValueInst *EI);
> - uint32_t lookup_or_add_call(CallInst *C);
> -
> -public:
> - ValueTable() : nextValueNumber(1) {}
> - uint32_t lookup_or_add(Value *V);
> - uint32_t lookup(Value *V) const;
> - uint32_t lookup_or_add_cmp(unsigned Opcode, CmpInst::Predicate Pred,
> - Value *LHS, Value *RHS);
> - bool exists(Value *V) const;
> - void add(Value *V, uint32_t num);
> - void clear();
> - void erase(Value *v);
> - void setAliasAnalysis(AliasAnalysis *A) { AA = A; }
> - AliasAnalysis *getAliasAnalysis() const { return AA; }
> - void setMemDep(MemoryDependenceResults *M) { MD = M; }
> - void setDomTree(DominatorTree *D) { DT = D; }
> - uint32_t getNextUnusedValueNumber() { return nextValueNumber; }
> - void verifyRemoved(const Value *) const;
> -};
> -
> -} // End anonymous namespace.
> -
> namespace llvm {
> template <> struct DenseMapInfo<Expression> {
> static inline Expression getEmptyKey() { return ~0U; }
> @@ -161,11 +117,119 @@ template <> struct DenseMapInfo<Expressi
> };
> } // End llvm namespace.
>
> +/// 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 llvm::gvn::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() {
> + 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 llvm::gvn::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);
> + }
> +};
> +
> //===----------------------------------------------------------------------===//
> // ValueTable Internal Functions
> //===----------------------------------------------------------------------===//
>
> -Expression ValueTable::create_expression(Instruction *I) {
> +Expression GVN::ValueTable::create_expression(Instruction *I) {
> Expression e;
> e.type = I->getType();
> e.opcode = I->getOpcode();
> @@ -199,7 +263,7 @@ Expression ValueTable::create_expression
> return e;
> }
>
> -Expression ValueTable::create_cmp_expression(unsigned Opcode,
> +Expression GVN::ValueTable::create_cmp_expression(unsigned Opcode,
> CmpInst::Predicate Predicate,
> Value *LHS, Value *RHS) {
> assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) &&
> @@ -218,7 +282,7 @@ Expression ValueTable::create_cmp_expres
> return e;
> }
>
> -Expression ValueTable::create_extractvalue_expression(ExtractValueInst *EI) {
> +Expression GVN::ValueTable::create_extractvalue_expression(ExtractValueInst *EI) {
> assert(EI && "Not an ExtractValueInst?");
> Expression e;
> e.type = EI->getType();
> @@ -274,12 +338,24 @@ Expression ValueTable::create_extractval
> // ValueTable External Functions
> //===----------------------------------------------------------------------===//
>
> +GVN::ValueTable::ValueTable() : nextValueNumber(1) {}
> +GVN::ValueTable::ValueTable(const ValueTable &Arg)
> + : valueNumbering(Arg.valueNumbering),
> + expressionNumbering(Arg.expressionNumbering), AA(Arg.AA), MD(Arg.MD),
> + DT(Arg.DT), nextValueNumber(Arg.nextValueNumber) {}
> +GVN::ValueTable::ValueTable(ValueTable &&Arg)
> + : valueNumbering(std::move(Arg.valueNumbering)),
> + expressionNumbering(std::move(Arg.expressionNumbering)),
> + AA(std::move(Arg.AA)), MD(std::move(Arg.MD)), DT(std::move(Arg.DT)),
> + nextValueNumber(std::move(Arg.nextValueNumber)) {}
> +GVN::ValueTable::~ValueTable() {}
> +
> /// add - Insert a value into the table with a specified value number.
> -void ValueTable::add(Value *V, uint32_t num) {
> +void GVN::ValueTable::add(Value *V, uint32_t num) {
> valueNumbering.insert(std::make_pair(V, num));
> }
>
> -uint32_t ValueTable::lookup_or_add_call(CallInst *C) {
> +uint32_t GVN::ValueTable::lookup_or_add_call(CallInst *C) {
> if (AA->doesNotAccessMemory(C)) {
> Expression exp = create_expression(C);
> uint32_t &e = expressionNumbering[exp];
> @@ -389,11 +465,11 @@ uint32_t ValueTable::lookup_or_add_call(
> }
>
> /// Returns true if a value number exists for the specified value.
> -bool ValueTable::exists(Value *V) const { return valueNumbering.count(V) != 0; }
> +bool GVN::ValueTable::exists(Value *V) const { return valueNumbering.count(V) != 0; }
>
> /// lookup_or_add - Returns the value number for the specified value, assigning
> /// it a new number if it did not have one before.
> -uint32_t ValueTable::lookup_or_add(Value *V) {
> +uint32_t GVN::ValueTable::lookup_or_add(Value *V) {
> DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
> if (VI != valueNumbering.end())
> return VI->second;
> @@ -464,7 +540,7 @@ uint32_t ValueTable::lookup_or_add(Value
>
> /// Returns the value number of the specified value. Fails if
> /// the value has not yet been numbered.
> -uint32_t ValueTable::lookup(Value *V) const {
> +uint32_t GVN::ValueTable::lookup(Value *V) const {
> DenseMap<Value*, uint32_t>::const_iterator VI = valueNumbering.find(V);
> assert(VI != valueNumbering.end() && "Value not numbered?");
> return VI->second;
> @@ -474,7 +550,7 @@ uint32_t ValueTable::lookup(Value *V) co
> /// assigning it a new number if it did not have one before. Useful when
> /// we deduced the result of a comparison, but don't immediately have an
> /// instruction realizing that comparison to hand.
> -uint32_t ValueTable::lookup_or_add_cmp(unsigned Opcode,
> +uint32_t GVN::ValueTable::lookup_or_add_cmp(unsigned Opcode,
> CmpInst::Predicate Predicate,
> Value *LHS, Value *RHS) {
> Expression exp = create_cmp_expression(Opcode, Predicate, LHS, RHS);
> @@ -484,20 +560,20 @@ uint32_t ValueTable::lookup_or_add_cmp(u
> }
>
> /// Remove all entries from the ValueTable.
> -void ValueTable::clear() {
> +void GVN::ValueTable::clear() {
> valueNumbering.clear();
> expressionNumbering.clear();
> nextValueNumber = 1;
> }
>
> /// Remove a value from the value numbering.
> -void ValueTable::erase(Value *V) {
> +void GVN::ValueTable::erase(Value *V) {
> valueNumbering.erase(V);
> }
>
> /// verifyRemoved - Verify that the value is removed from all internal data
> /// structures.
> -void ValueTable::verifyRemoved(const Value *V) const {
> +void GVN::ValueTable::verifyRemoved(const Value *V) const {
> for (DenseMap<Value*, uint32_t>::const_iterator
> I = valueNumbering.begin(), E = valueNumbering.end(); I != E; ++I) {
> assert(I->first != V && "Inst still occurs in value numbering map!");
> @@ -508,287 +584,15 @@ void ValueTable::verifyRemoved(const Val
> // GVN Pass
> //===----------------------------------------------------------------------===//
>
> -namespace {
> -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() {
> - 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;
> -
> - // Block-local map of equivalent values to their leader, does not
> - // propagate to any successors. Entries added mid-block are applied
> - // to the remaining instructions in the block.
> - SmallMapVector<llvm::Value *, llvm::Constant *, 4> ReplaceWithConstMap;
> - SmallVector<Instruction *, 8> InstrsToErase;
> -
> - typedef SmallVector<NonLocalDepResult, 64> LoadDepVect;
> - typedef SmallVector<AvailableValueInBlock, 64> AvailValInBlkVect;
> - typedef SmallVector<BasicBlock *, 64> UnavailBlkVect;
> -
> -public:
> - static char ID; // Pass identification, replacement for typeid
> - explicit GVN(bool noloads = false)
> - : FunctionPass(ID), NoLoads(noloads), MD(nullptr) {
> - initializeGVNPass(*PassRegistry::getPassRegistry());
> - }
> -
> - bool runOnFunction(Function &F) override;
> -
> - /// This removes the specified instruction from
> - /// our various maps and marks it for deletion.
> - void markInstructionForDeletion(Instruction *I) {
> - VN.erase(I);
> - InstrsToErase.push_back(I);
> - }
> -
> - DominatorTree &getDominatorTree() const { return *DT; }
> - AliasAnalysis *getAliasAnalysis() const { return VN.getAliasAnalysis(); }
> - 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>();
> - Node->Val = V;
> - Node->BB = BB;
> - Node->Next = Curr.Next;
> - Curr.Next = Node;
> - }
> -
> - /// 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 {
> - if (!Curr->Next) {
> - Curr->Val = nullptr;
> - Curr->BB = nullptr;
> - } else {
> - 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.
> - SmallVector<std::pair<TerminatorInst *, unsigned>, 4> toSplit;
> -
> - // This transformation requires dominator postdominator info
> - void getAnalysisUsage(AnalysisUsage &AU) const override {
> - AU.addRequired<AssumptionCacheTracker>();
> - AU.addRequired<DominatorTreeWrapperPass>();
> - AU.addRequired<TargetLibraryInfoWrapperPass>();
> - if (!NoLoads)
> - AU.addRequired<MemoryDependenceWrapperPass>();
> - AU.addRequired<AAResultsWrapperPass>();
> -
> - AU.addPreserved<DominatorTreeWrapperPass>();
> - 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);
> -
> - // Other helper routines
> - 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...
> -FunctionPass *llvm::createGVNPass(bool NoLoads) {
> - return new GVN(NoLoads);
> +PreservedAnalyses GVN::run(Function &F, AnalysisManager<Function> *AM) {
> + bool Changed = runImpl(F, AM->getResult<AssumptionAnalysis>(F),
> + AM->getResult<DominatorTreeAnalysis>(F),
> + AM->getResult<TargetLibraryAnalysis>(F),
> + AM->getResult<AAManager>(F),
> + &AM->getResult<MemoryDependenceAnalysis>(F));
> + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
> }
>
> -INITIALIZE_PASS_BEGIN(GVN, "gvn", "Global Value Numbering", false, false)
> -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
> -INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
> -INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
> -INITIALIZE_PASS_END(GVN, "gvn", "Global Value Numbering", false, false)
> -
> #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
> void GVN::dump(DenseMap<uint32_t, Value*>& d) {
> errs() << "{\n";
> @@ -2350,18 +2154,16 @@ bool GVN::processInstruction(Instruction
> }
>
> /// runOnFunction - This is the main transformation entry point for a function.
> -bool GVN::runOnFunction(Function& F) {
> - if (skipOptnoneFunction(F))
> - return false;
> -
> - if (!NoLoads)
> - MD = &getAnalysis<MemoryDependenceWrapperPass>().getMemDep();
> - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
> - AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
> - TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
> - VN.setAliasAnalysis(&getAnalysis<AAResultsWrapperPass>().getAAResults());
> - VN.setMemDep(MD);
> +bool GVN::runImpl(Function &F, AssumptionCache &RunAC, DominatorTree &RunDT,
> + const TargetLibraryInfo &RunTLI, AAResults &RunAA,
> + MemoryDependenceResults *RunMD) {
> + AC = &RunAC;
> + DT = &RunDT;
> VN.setDomTree(DT);
> + TLI = &RunTLI;
> + VN.setAliasAnalysis(&RunAA);
> + MD = RunMD;
> + VN.setMemDep(MD);
>
> bool Changed = false;
> bool ShouldContinue = true;
> @@ -2857,3 +2659,57 @@ void GVN::assignValNumForDeadCode() {
> }
> }
> }
> +
> +class llvm::gvn::GVNLegacyPass : public FunctionPass {
> +public:
> + static char ID; // Pass identification, replacement for typeid
> + explicit GVNLegacyPass(bool NoLoads = false)
> + : FunctionPass(ID), NoLoads(NoLoads) {
> + initializeGVNLegacyPassPass(*PassRegistry::getPassRegistry());
> + }
> +
> + bool runOnFunction(Function &F) override {
> + if (skipOptnoneFunction(F))
> + return false;
> +
> + return Impl.runImpl(
> + F, getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F),
> + getAnalysis<DominatorTreeWrapperPass>().getDomTree(),
> + getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
> + getAnalysis<AAResultsWrapperPass>().getAAResults(),
> + NoLoads ? nullptr
> + : &getAnalysis<MemoryDependenceWrapperPass>().getMemDep());
> + }
> +
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.addRequired<AssumptionCacheTracker>();
> + AU.addRequired<DominatorTreeWrapperPass>();
> + AU.addRequired<TargetLibraryInfoWrapperPass>();
> + if (!NoLoads)
> + AU.addRequired<MemoryDependenceWrapperPass>();
> + AU.addRequired<AAResultsWrapperPass>();
> +
> + AU.addPreserved<DominatorTreeWrapperPass>();
> + AU.addPreserved<GlobalsAAWrapperPass>();
> + }
> +
> +private:
> + bool NoLoads;
> + GVN Impl;
> +};
> +
> +char GVNLegacyPass::ID = 0;
> +
> +// The public interface to this file...
> +FunctionPass *llvm::createGVNPass(bool NoLoads) {
> + return new GVNLegacyPass(NoLoads);
> +}
> +
> +INITIALIZE_PASS_BEGIN(GVNLegacyPass, "gvn", "Global Value Numbering", false, false)
> +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
> +INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
> +INITIALIZE_PASS_END(GVNLegacyPass, "gvn", "Global Value Numbering", false, false)
>
> Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Fri Mar 11 02:50:55 2016
> @@ -20,6 +20,7 @@
> #include "llvm/Analysis/Passes.h"
> #include "llvm/Analysis/ScopedNoAliasAA.h"
> #include "llvm/Analysis/TypeBasedAliasAnalysis.h"
> +#include "llvm/Transforms/Scalar/GVN.h"
> #include "llvm/IR/DataLayout.h"
> #include "llvm/IR/Verifier.h"
> #include "llvm/InitializePasses.h"
> @@ -40,7 +41,7 @@ void llvm::initializeScalarOpts(PassRegi
> initializeDeadInstEliminationPass(Registry);
> initializeScalarizerPass(Registry);
> initializeDSEPass(Registry);
> - initializeGVNPass(Registry);
> + initializeGVNLegacyPassPass(Registry);
> initializeEarlyCSELegacyPassPass(Registry);
> initializeFlattenCFGPassPass(Registry);
> initializeInductiveRangeCheckEliminationPass(Registry);
>
> Modified: llvm/trunk/test/Transforms/GVN/basic.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/basic.ll?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/GVN/basic.ll (original)
> +++ llvm/trunk/test/Transforms/GVN/basic.ll Fri Mar 11 02:50:55 2016
> @@ -1,4 +1,5 @@
> ; RUN: opt < %s -gvn -S | not grep "%z2 ="
> +; RUN: opt < %s -passes=gvn -S | not grep "%z2 ="
This should probably use FileCheck rather than grep.
>
> define i32 @main() {
> block1:
>
> Modified: llvm/trunk/test/Transforms/GVN/pre-gep-load.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/pre-gep-load.ll?rev=263208&r1=263207&r2=263208&view=diff
> ==============================================================================
> --- llvm/trunk/test/Transforms/GVN/pre-gep-load.ll (original)
> +++ llvm/trunk/test/Transforms/GVN/pre-gep-load.ll Fri Mar 11 02:50:55 2016
> @@ -1,4 +1,6 @@
> ; RUN: opt < %s -basicaa -gvn -enable-load-pre -S | FileCheck %s
> +; RUN: opt < %s -aa-pipeline=basic-aa -passes=gvn -enable-load-pre -S | FileCheck %s
> +
> target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
> target triple = "aarch64--linux-gnu"
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list