[llvm-commits] [parallel] CVS: llvm/lib/Analysis/ProfileInfo.cpp ProfileInfoLoader.cpp ProfileInfoLoaderPass.cpp AliasAnalysis.cpp BasicAliasAnalysis.cpp LoadValueNumbering.cpp LoopInfo.cpp ValueNumbering.cpp
Misha Brukman
brukman at cs.uiuc.edu
Mon Mar 1 18:03:14 PST 2004
Changes in directory llvm/lib/Analysis:
ProfileInfo.cpp added (r1.3.2.1)
ProfileInfoLoader.cpp added (r1.2.2.1)
ProfileInfoLoaderPass.cpp added (r1.3.2.1)
AliasAnalysis.cpp updated: 1.15 -> 1.15.4.1
BasicAliasAnalysis.cpp updated: 1.26 -> 1.26.2.1
LoadValueNumbering.cpp updated: 1.10 -> 1.10.4.1
LoopInfo.cpp updated: 1.46 -> 1.46.2.1
ValueNumbering.cpp updated: 1.9 -> 1.9.4.1
---
Log message:
Merge from trunk
---
Diffs of the changes: (+607 -257)
Index: llvm/lib/Analysis/ProfileInfo.cpp
diff -c /dev/null llvm/lib/Analysis/ProfileInfo.cpp:1.3.2.1
*** /dev/null Mon Mar 1 17:58:27 2004
--- llvm/lib/Analysis/ProfileInfo.cpp Mon Mar 1 17:58:12 2004
***************
*** 0 ****
--- 1,42 ----
+ //===- ProfileInfo.cpp - Profile Info Interface ---------------------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements the abstract ProfileInfo interface, and the default
+ // "no profile" implementation.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "llvm/Analysis/ProfileInfo.h"
+ #include "llvm/Pass.h"
+ using namespace llvm;
+
+ // Register the ProfileInfo interface, providing a nice name to refer to.
+ namespace {
+ RegisterAnalysisGroup<ProfileInfo> Z("Profile Information");
+ }
+
+ ProfileInfo::~ProfileInfo() {}
+
+
+ //===----------------------------------------------------------------------===//
+ // NoProfile ProfileInfo implementation
+ //
+
+ namespace {
+ struct NoProfileInfo : public ImmutablePass, public ProfileInfo {
+ unsigned getExecutionCount(BasicBlock *BB) { return 0; }
+ };
+
+ // Register this pass...
+ RegisterOpt<NoProfileInfo>
+ X("no-profile", "No Profile Information");
+
+ // Declare that we implement the ProfileInfo interface
+ RegisterAnalysisGroup<ProfileInfo, NoProfileInfo, true> Y;
+ } // End of anonymous namespace
Index: llvm/lib/Analysis/ProfileInfoLoader.cpp
diff -c /dev/null llvm/lib/Analysis/ProfileInfoLoader.cpp:1.2.2.1
*** /dev/null Mon Mar 1 17:58:27 2004
--- llvm/lib/Analysis/ProfileInfoLoader.cpp Mon Mar 1 17:58:12 2004
***************
*** 0 ****
--- 1,180 ----
+ //===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // The ProfileInfoLoader class is used to load and represent profiling
+ // information read in from the dump file.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "llvm/Analysis/ProfileInfoLoader.h"
+ #include "llvm/Module.h"
+ #include <cstdio>
+ using namespace llvm;
+
+ enum ProfilingType {
+ ArgumentInfo = 1, // The command line argument block
+ FunctionInfo = 2, // Function profiling information
+ BlockInfo = 3, // Block profiling information
+ };
+
+ // ByteSwap - Byteswap 'Var' if 'Really' is true.
+ //
+ static inline unsigned ByteSwap(unsigned Var, bool Really) {
+ if (!Really) return Var;
+ return ((Var & (255<< 0)) << 24) |
+ ((Var & (255<< 8)) << 8) |
+ ((Var & (255<<16)) >> 8) |
+ ((Var & (255<<24)) >> 24);
+ }
+
+ static void ReadProfilingBlock(const char *ToolName, FILE *F,
+ bool ShouldByteSwap,
+ std::vector<unsigned> &Data) {
+ // Read the number of entries...
+ unsigned NumEntries;
+ if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
+ std::cerr << ToolName << ": data packet truncated!\n";
+ perror(0);
+ exit(1);
+ }
+ NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
+
+ // Read the counts...
+ std::vector<unsigned> TempSpace(NumEntries);
+
+ // Read in the block of data...
+ if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
+ std::cerr << ToolName << ": data packet truncated!\n";
+ perror(0);
+ exit(1);
+ }
+
+ // Make sure we have enough space...
+ if (Data.size() < NumEntries)
+ Data.resize(NumEntries);
+
+ // Accumulate the data we just read into the data.
+ if (!ShouldByteSwap) {
+ for (unsigned i = 0; i != NumEntries; ++i)
+ Data[i] += TempSpace[i];
+ } else {
+ for (unsigned i = 0; i != NumEntries; ++i)
+ Data[i] += ByteSwap(TempSpace[i], true);
+ }
+ }
+
+ // ProfileInfoLoader ctor - Read the specified profiling data file, exiting the
+ // program if the file is invalid or broken.
+ //
+ ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
+ const std::string &Filename,
+ Module &TheModule) : M(TheModule) {
+ FILE *F = fopen(Filename.c_str(), "r");
+ if (F == 0) {
+ std::cerr << ToolName << ": Error opening '" << Filename << "': ";
+ perror(0);
+ exit(1);
+ }
+
+ // Keep reading packets until we run out of them.
+ unsigned PacketType;
+ while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
+ // If the low eight bits of the packet are zero, we must be dealing with an
+ // endianness mismatch. Byteswap all words read from the profiling
+ // information.
+ bool ShouldByteSwap = (char)PacketType == 0;
+ PacketType = ByteSwap(PacketType, ShouldByteSwap);
+
+ switch (PacketType) {
+ case ArgumentInfo: {
+ unsigned ArgLength;
+ if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) {
+ std::cerr << ToolName << ": arguments packet truncated!\n";
+ perror(0);
+ exit(1);
+ }
+ ArgLength = ByteSwap(ArgLength, ShouldByteSwap);
+
+ // Read in the arguments...
+ std::vector<char> Chars(ArgLength+4);
+
+ if (ArgLength)
+ if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) {
+ std::cerr << ToolName << ": arguments packet truncated!\n";
+ perror(0);
+ exit(1);
+ }
+ CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
+ break;
+ }
+
+ case FunctionInfo:
+ ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
+ break;
+
+ case BlockInfo:
+ ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
+ break;
+
+ default:
+ std::cerr << ToolName << ": Unknown packet type #" << PacketType << "!\n";
+ exit(1);
+ }
+ }
+
+ fclose(F);
+ }
+
+
+ // getFunctionCounts - This method is used by consumers of function counting
+ // information. If we do not directly have function count information, we
+ // compute it from other, more refined, types of profile information.
+ //
+ void ProfileInfoLoader::getFunctionCounts(std::vector<std::pair<Function*,
+ unsigned> > &Counts) {
+ if (FunctionCounts.empty()) {
+ // Synthesize function frequency information from the number of times their
+ // entry blocks were executed.
+ std::vector<std::pair<BasicBlock*, unsigned> > BlockCounts;
+ getBlockCounts(BlockCounts);
+
+ for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i)
+ if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first)
+ Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(),
+ BlockCounts[i].second));
+ return;
+ }
+
+ unsigned Counter = 0;
+ for (Module::iterator I = M.begin(), E = M.end();
+ I != E && Counter != FunctionCounts.size(); ++I)
+ if (!I->isExternal())
+ Counts.push_back(std::make_pair(I, FunctionCounts[Counter++]));
+ }
+
+ // getBlockCounts - This method is used by consumers of block counting
+ // information. If we do not directly have block count information, we
+ // compute it from other, more refined, types of profile information.
+ //
+ void ProfileInfoLoader::getBlockCounts(std::vector<std::pair<BasicBlock*,
+ unsigned> > &Counts) {
+ if (BlockCounts.empty()) {
+ std::cerr << "Block counts not available, and no synthesis "
+ << "is implemented yet!\n";
+ return;
+ }
+
+ unsigned Counter = 0;
+ for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ Counts.push_back(std::make_pair(BB, BlockCounts[Counter++]));
+ if (Counter == BlockCounts.size())
+ return;
+ }
+ }
Index: llvm/lib/Analysis/ProfileInfoLoaderPass.cpp
diff -c /dev/null llvm/lib/Analysis/ProfileInfoLoaderPass.cpp:1.3.2.1
*** /dev/null Mon Mar 1 17:58:28 2004
--- llvm/lib/Analysis/ProfileInfoLoaderPass.cpp Mon Mar 1 17:58:12 2004
***************
*** 0 ****
--- 1,75 ----
+ //===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This file implements a concrete implementation of profiling information that
+ // loads the information from a profile dump file.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "llvm/Pass.h"
+ #include "llvm/Analysis/ProfileInfo.h"
+ #include "llvm/Analysis/ProfileInfoLoader.h"
+ #include "Support/CommandLine.h"
+ using namespace llvm;
+
+ namespace {
+ cl::opt<std::string>
+ ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"),
+ cl::value_desc("filename"),
+ cl::desc("Profile file loaded by -profile-loader"));
+
+ class LoaderPass : public Pass, public ProfileInfo {
+ std::string Filename;
+ std::map<BasicBlock*, unsigned> ExecutionCounts;
+ public:
+ LoaderPass(const std::string &filename = "")
+ : Filename(filename) {
+ if (filename.empty()) Filename = ProfileInfoFilename;
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+
+ virtual const char *getPassName() const {
+ return "Profiling information loader";
+ }
+
+ /// run - Load the profile information from the specified file.
+ virtual bool run(Module &M);
+
+ virtual unsigned getExecutionCount(BasicBlock *BB) {
+ std::map<BasicBlock*, unsigned>::iterator I = ExecutionCounts.find(BB);
+ return I != ExecutionCounts.end() ? I->second : 0;
+ }
+ };
+
+ RegisterOpt<LoaderPass>
+ X("profile-loader", "Load profile information from llvmprof.out");
+
+ RegisterAnalysisGroup<ProfileInfo, LoaderPass> Y;
+ } // End of anonymous namespace
+
+
+ /// createProfileLoaderPass - This function returns a Pass that loads the
+ /// profiling information for the module from the specified filename, making it
+ /// available to the optimizers.
+ Pass *llvm::createProfileLoaderPass(const std::string &Filename) {
+ return new LoaderPass(Filename);
+ }
+
+ bool LoaderPass::run(Module &M) {
+ ProfileInfoLoader PIL("opt", Filename, M);
+ if (PIL.hasAccurateBlockCounts()) {
+ std::vector<std::pair<BasicBlock*, unsigned> > Counts;
+ PIL.getBlockCounts(Counts);
+ ExecutionCounts.insert(Counts.begin(), Counts.end());
+ }
+ return false;
+ }
Index: llvm/lib/Analysis/AliasAnalysis.cpp
diff -u llvm/lib/Analysis/AliasAnalysis.cpp:1.15 llvm/lib/Analysis/AliasAnalysis.cpp:1.15.4.1
--- llvm/lib/Analysis/AliasAnalysis.cpp:1.15 Tue Nov 11 16:41:31 2003
+++ llvm/lib/Analysis/AliasAnalysis.cpp Mon Mar 1 17:58:12 2004
@@ -44,8 +44,15 @@
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) {
- return alias(S->getOperand(1), TD->getTypeSize(S->getOperand(0)->getType()),
- P, Size) ? Mod : NoModRef;
+ // If the stored address cannot alias the pointer in question, then the
+ // pointer cannot be modified by the store.
+ if (!alias(S->getOperand(1), TD->getTypeSize(S->getOperand(0)->getType()),
+ P, Size))
+ return NoModRef;
+
+ // If the pointer is a pointer to constant memory, then it could not have been
+ // modified by this store.
+ return pointsToConstantMemory(P) ? NoModRef : Mod;
}
Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp
diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.26 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.26.2.1
--- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.26 Mon Jan 12 11:57:32 2004
+++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Mon Mar 1 17:58:12 2004
@@ -14,7 +14,9 @@
// FIXME: This could be extended for a very simple form of mod/ref information.
// If a pointer is locally allocated (either malloc or alloca) and never passed
// into a call or stored to memory, then we know that calls will not mod/ref the
-// memory. This can be important for tailcallelim.
+// memory. This can be important for tailcallelim, and can support CSE of loads
+// and dead store elimination across calls. This is particularly important for
+// stack allocated arrays.
//
//===----------------------------------------------------------------------===//
@@ -22,8 +24,9 @@
#include "llvm/Pass.h"
#include "llvm/Argument.h"
#include "llvm/iOther.h"
+#include "llvm/iMemory.h"
#include "llvm/Constants.h"
-#include "llvm/GlobalValue.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
@@ -41,10 +44,13 @@
virtual void initializePass();
- // alias - This is the only method here that does anything interesting...
- //
AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size);
+
+ /// pointsToConstantMemory - Chase pointers until we find a (constant
+ /// global) or not.
+ bool pointsToConstantMemory(const Value *P);
+
private:
// CheckGEPInstructions - Check two GEP instructions with known
// must-aliasing base pointers. This checks to see if the index expressions
@@ -124,6 +130,14 @@
return V;
}
+/// pointsToConstantMemory - Chase pointers until we find a (constant
+/// global) or not.
+bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
+ if (const Value *V = getUnderlyingObject(P))
+ if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
+ return GV->isConstant();
+ return false;
+}
// alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such
// as array references. Note that this function is heavily tail recursive.
Index: llvm/lib/Analysis/LoadValueNumbering.cpp
diff -u llvm/lib/Analysis/LoadValueNumbering.cpp:1.10 llvm/lib/Analysis/LoadValueNumbering.cpp:1.10.4.1
--- llvm/lib/Analysis/LoadValueNumbering.cpp:1.10 Tue Nov 11 16:41:31 2003
+++ llvm/lib/Analysis/LoadValueNumbering.cpp Mon Mar 1 17:58:12 2004
@@ -28,10 +28,8 @@
#include "llvm/iMemory.h"
#include "llvm/BasicBlock.h"
#include "llvm/Support/CFG.h"
-#include <algorithm>
#include <set>
-
-namespace llvm {
+using namespace llvm;
namespace {
// FIXME: This should not be a FunctionPass.
@@ -52,17 +50,6 @@
///
virtual void getEqualNumberNodes(Value *V1,
std::vector<Value*> &RetVals) const;
- private:
- /// haveEqualValueNumber - Given two load instructions, determine if they
- /// both produce the same value on every execution of the program, assuming
- /// that their source operands always give the same value. This uses the
- /// AliasAnalysis implementation to invalidate loads when stores or function
- /// calls occur that could modify the value produced by the load.
- ///
- bool haveEqualValueNumber(LoadInst *LI, LoadInst *LI2, AliasAnalysis &AA,
- DominatorSet &DomSetInfo) const;
- bool haveEqualValueNumber(LoadInst *LI, StoreInst *SI, AliasAnalysis &AA,
- DominatorSet &DomSetInfo) const;
};
// Register this pass...
@@ -72,7 +59,7 @@
RegisterAnalysisGroup<ValueNumbering, LoadVN> Y;
}
-Pass *createLoadValueNumberingPass() { return new LoadVN(); }
+Pass *llvm::createLoadValueNumberingPass() { return new LoadVN(); }
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering and
@@ -86,6 +73,43 @@
AU.addRequired<TargetData>();
}
+static bool isPathTransparentTo(BasicBlock *CurBlock, BasicBlock *Dom,
+ Value *Ptr, unsigned Size, AliasAnalysis &AA,
+ std::set<BasicBlock*> &Visited,
+ std::map<BasicBlock*, bool> &TransparentBlocks){
+ // If we have already checked out this path, or if we reached our destination,
+ // stop searching, returning success.
+ if (CurBlock == Dom || !Visited.insert(CurBlock).second)
+ return true;
+
+ // Check whether this block is known transparent or not.
+ std::map<BasicBlock*, bool>::iterator TBI =
+ TransparentBlocks.lower_bound(CurBlock);
+
+ if (TBI == TransparentBlocks.end() || TBI->first != CurBlock) {
+ // If this basic block can modify the memory location, then the path is not
+ // transparent!
+ if (AA.canBasicBlockModify(*CurBlock, Ptr, Size)) {
+ TransparentBlocks.insert(TBI, std::make_pair(CurBlock, false));
+ return false;
+ }
+ TransparentBlocks.insert(TBI, std::make_pair(CurBlock, true));
+ } else if (!TBI->second)
+ // This block is known non-transparent, so that path can't be either.
+ return false;
+
+ // The current block is known to be transparent. The entire path is
+ // transparent if all of the predecessors paths to the parent is also
+ // transparent to the memory location.
+ for (pred_iterator PI = pred_begin(CurBlock), E = pred_end(CurBlock);
+ PI != E; ++PI)
+ if (!isPathTransparentTo(*PI, Dom, Ptr, Size, AA, Visited,
+ TransparentBlocks))
+ return false;
+ return true;
+}
+
+
// getEqualNumberNodes - Return nodes with the same value number as the
// specified Value. This fills in the argument vector with any equal values.
//
@@ -96,249 +120,260 @@
if (isa<PointerType>(V->getType()))
getAnalysis<AliasAnalysis>().getMustAliases(V, RetVals);
- if (LoadInst *LI = dyn_cast<LoadInst>(V)) {
- // Volatile loads cannot be replaced with the value of other loads.
- if (LI->isVolatile())
- return getAnalysis<ValueNumbering>().getEqualNumberNodes(V, RetVals);
-
- // If we have a load instruction, find all of the load and store
- // instructions that use the same source operand. We implement this
- // recursively, because there could be a load of a load of a load that are
- // all identical. We are guaranteed that this cannot be an infinite
- // recursion because load instructions would have to pass through a PHI node
- // in order for there to be a cycle. The PHI node would be handled by the
- // else case here, breaking the infinite recursion.
- //
- std::vector<Value*> PointerSources;
- getEqualNumberNodes(LI->getOperand(0), PointerSources);
- PointerSources.push_back(LI->getOperand(0));
-
- Function *F = LI->getParent()->getParent();
-
- // Now that we know the set of equivalent source pointers for the load
- // instruction, look to see if there are any load or store candidates that
- // are identical.
- //
- std::vector<LoadInst*> CandidateLoads;
- std::vector<StoreInst*> CandidateStores;
-
- while (!PointerSources.empty()) {
- Value *Source = PointerSources.back();
- PointerSources.pop_back(); // Get a source pointer...
-
- for (Value::use_iterator UI = Source->use_begin(), UE = Source->use_end();
- UI != UE; ++UI)
- if (LoadInst *Cand = dyn_cast<LoadInst>(*UI)) {// Is a load of source?
- if (Cand->getParent()->getParent() == F && // In the same function?
- Cand != LI && !Cand->isVolatile()) // Not LI itself?
- CandidateLoads.push_back(Cand); // Got one...
- } else if (StoreInst *Cand = dyn_cast<StoreInst>(*UI)) {
- if (Cand->getParent()->getParent() == F && !Cand->isVolatile() &&
- Cand->getOperand(1) == Source) // It's a store THROUGH the ptr...
- CandidateStores.push_back(Cand);
- }
- }
-
- // Remove duplicates from the CandidateLoads list because alias analysis
- // processing may be somewhat expensive and we don't want to do more work
- // than necessary.
- //
- unsigned OldSize = CandidateLoads.size();
- std::sort(CandidateLoads.begin(), CandidateLoads.end());
- CandidateLoads.erase(std::unique(CandidateLoads.begin(),
- CandidateLoads.end()),
- CandidateLoads.end());
- // FIXME: REMOVE THIS SORTING AND UNIQUING IF IT CAN'T HAPPEN
- assert(CandidateLoads.size() == OldSize && "Shrunk the candloads list?");
-
- // Get Alias Analysis...
- AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
- DominatorSet &DomSetInfo = getAnalysis<DominatorSet>();
-
- // Loop over all of the candidate loads. If they are not invalidated by
- // stores or calls between execution of them and LI, then add them to
- // RetVals.
- for (unsigned i = 0, e = CandidateLoads.size(); i != e; ++i)
- if (haveEqualValueNumber(LI, CandidateLoads[i], AA, DomSetInfo))
- RetVals.push_back(CandidateLoads[i]);
- for (unsigned i = 0, e = CandidateStores.size(); i != e; ++i)
- if (haveEqualValueNumber(LI, CandidateStores[i], AA, DomSetInfo))
- RetVals.push_back(CandidateStores[i]->getOperand(0));
-
- } else {
+ if (!isa<LoadInst>(V)) {
+ // Not a load instruction? Just chain to the base value numbering
+ // implementation to satisfy the request...
assert(&getAnalysis<ValueNumbering>() != (ValueNumbering*)this &&
"getAnalysis() returned this!");
- // Not a load instruction? Just chain to the base value numbering
- // implementation to satisfy the request...
return getAnalysis<ValueNumbering>().getEqualNumberNodes(V, RetVals);
}
-}
-
-// CheckForInvalidatingInst - Return true if BB or any of the predecessors of BB
-// (until DestBB) contain an instruction that might invalidate Ptr.
-//
-static bool CheckForInvalidatingInst(BasicBlock *BB, BasicBlock *DestBB,
- Value *Ptr, unsigned Size,
- AliasAnalysis &AA,
- std::set<BasicBlock*> &VisitedSet) {
- // Found the termination point!
- if (BB == DestBB || VisitedSet.count(BB)) return false;
-
- // Avoid infinite recursion!
- VisitedSet.insert(BB);
-
- // Can this basic block modify Ptr?
- if (AA.canBasicBlockModify(*BB, Ptr, Size))
- return true;
-
- // Check all of our predecessor blocks...
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI)
- if (CheckForInvalidatingInst(*PI, DestBB, Ptr, Size, AA, VisitedSet))
- return true;
-
- // None of our predecessor blocks contain an invalidating instruction, and we
- // don't either!
- return false;
-}
-
-/// haveEqualValueNumber - Given two load instructions, determine if they both
-/// produce the same value on every execution of the program, assuming that
-/// their source operands always give the same value. This uses the
-/// AliasAnalysis implementation to invalidate loads when stores or function
-/// calls occur that could modify the value produced by the load.
-///
-bool LoadVN::haveEqualValueNumber(LoadInst *L1, LoadInst *L2,
- AliasAnalysis &AA,
- DominatorSet &DomSetInfo) const {
- // Figure out which load dominates the other one. If neither dominates the
- // other we cannot eliminate them.
+ // Volatile loads cannot be replaced with the value of other loads.
+ LoadInst *LI = cast<LoadInst>(V);
+ if (LI->isVolatile())
+ return getAnalysis<ValueNumbering>().getEqualNumberNodes(V, RetVals);
+
+ // If we have a load instruction, find all of the load and store instructions
+ // that use the same source operand. We implement this recursively, because
+ // there could be a load of a load of a load that are all identical. We are
+ // guaranteed that this cannot be an infinite recursion because load
+ // instructions would have to pass through a PHI node in order for there to be
+ // a cycle. The PHI node would be handled by the else case here, breaking the
+ // infinite recursion.
//
- // FIXME: This could be enhanced to some cases with a shared dominator!
+ std::vector<Value*> PointerSources;
+ getEqualNumberNodes(LI->getOperand(0), PointerSources);
+ PointerSources.push_back(LI->getOperand(0));
+
+ BasicBlock *LoadBB = LI->getParent();
+ Function *F = LoadBB->getParent();
+
+ // Now that we know the set of equivalent source pointers for the load
+ // instruction, look to see if there are any load or store candidates that are
+ // identical.
//
- if (DomSetInfo.dominates(L2, L1))
- std::swap(L1, L2); // Make L1 dominate L2
- else if (!DomSetInfo.dominates(L1, L2))
- return false; // Neither instruction dominates the other one...
-
- BasicBlock *BB1 = L1->getParent(), *BB2 = L2->getParent();
- Value *LoadAddress = L1->getOperand(0);
-
- assert(L1->getType() == L2->getType() &&
- "How could the same source pointer return different types?");
-
+ std::map<BasicBlock*, std::vector<LoadInst*> > CandidateLoads;
+ std::map<BasicBlock*, std::vector<StoreInst*> > CandidateStores;
+
+ while (!PointerSources.empty()) {
+ Value *Source = PointerSources.back();
+ PointerSources.pop_back(); // Get a source pointer...
+
+ for (Value::use_iterator UI = Source->use_begin(), UE = Source->use_end();
+ UI != UE; ++UI)
+ if (LoadInst *Cand = dyn_cast<LoadInst>(*UI)) {// Is a load of source?
+ if (Cand->getParent()->getParent() == F && // In the same function?
+ Cand != LI && !Cand->isVolatile()) // Not LI itself?
+ CandidateLoads[Cand->getParent()].push_back(Cand); // Got one...
+ } else if (StoreInst *Cand = dyn_cast<StoreInst>(*UI)) {
+ if (Cand->getParent()->getParent() == F && !Cand->isVolatile() &&
+ Cand->getOperand(1) == Source) // It's a store THROUGH the ptr...
+ CandidateStores[Cand->getParent()].push_back(Cand);
+ }
+ }
+
+ // Get alias analysis & dominators.
+ AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
+ DominatorSet &DomSetInfo = getAnalysis<DominatorSet>();
+ Value *LoadPtr = LI->getOperand(0);
// Find out how many bytes of memory are loaded by the load instruction...
- unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(L1->getType());
+ unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(LI->getType());
- // L1 now dominates L2. Check to see if the intervening instructions between
- // the two loads include a store or call...
- //
- if (BB1 == BB2) { // In same basic block?
- // In this degenerate case, no checking of global basic blocks has to occur
- // just check the instructions BETWEEN L1 & L2...
- //
- if (AA.canInstructionRangeModify(*L1, *L2, LoadAddress, LoadSize))
- return false; // Cannot eliminate load
+ // Find all of the candidate loads and stores that are in the same block as
+ // the defining instruction.
+ std::set<Instruction*> Instrs;
+ Instrs.insert(CandidateLoads[LoadBB].begin(), CandidateLoads[LoadBB].end());
+ CandidateLoads.erase(LoadBB);
+ Instrs.insert(CandidateStores[LoadBB].begin(), CandidateStores[LoadBB].end());
+ CandidateStores.erase(LoadBB);
+
+ // Figure out if the load is invalidated from the entry of the block it is in
+ // until the actual instruction. This scans the block backwards from LI. If
+ // we see any candidate load or store instructions, then we know that the
+ // candidates have the same value # as LI.
+ bool LoadInvalidatedInBBBefore = false;
+ for (BasicBlock::iterator I = LI; I != LoadBB->begin(); ) {
+ --I;
+ // If this instruction is a candidate load before LI, we know there are no
+ // invalidating instructions between it and LI, so they have the same value
+ // number.
+ if (isa<LoadInst>(I) && Instrs.count(I)) {
+ RetVals.push_back(I);
+ Instrs.erase(I);
+ }
- // No instructions invalidate the loads, they produce the same value!
- return true;
- } else {
- // Make sure that there are no store instructions between L1 and the end of
- // its basic block...
- //
- if (AA.canInstructionRangeModify(*L1, *BB1->getTerminator(), LoadAddress,
- LoadSize))
- return false; // Cannot eliminate load
-
- // Make sure that there are no store instructions between the start of BB2
- // and the second load instruction...
- //
- if (AA.canInstructionRangeModify(BB2->front(), *L2, LoadAddress, LoadSize))
- return false; // Cannot eliminate load
-
- // Do a depth first traversal of the inverse CFG starting at L2's block,
- // looking for L1's block. The inverse CFG is made up of the predecessor
- // nodes of a block... so all of the edges in the graph are "backward".
- //
- std::set<BasicBlock*> VisitedSet;
- for (pred_iterator PI = pred_begin(BB2), PE = pred_end(BB2); PI != PE; ++PI)
- if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, LoadSize, AA,
- VisitedSet))
- return false;
+ if (AA.getModRefInfo(I, LoadPtr, LoadSize) & AliasAnalysis::Mod) {
+ // If the invalidating instruction is a store, and its in our candidate
+ // set, then we can do store-load forwarding: the load has the same value
+ // # as the stored value.
+ if (isa<StoreInst>(I) && Instrs.count(I)) {
+ Instrs.erase(I);
+ RetVals.push_back(I->getOperand(0));
+ }
- // If we passed all of these checks then we are sure that the two loads
- // produce the same value.
- return true;
+ LoadInvalidatedInBBBefore = true;
+ break;
+ }
}
-}
-
-/// haveEqualValueNumber - Given a load instruction and a store instruction,
-/// determine if the stored value reaches the loaded value unambiguously on
-/// every execution of the program. This uses the AliasAnalysis implementation
-/// to invalidate the stored value when stores or function calls occur that
-/// could modify the value produced by the load.
-///
-bool LoadVN::haveEqualValueNumber(LoadInst *Load, StoreInst *Store,
- AliasAnalysis &AA,
- DominatorSet &DomSetInfo) const {
- // If the store does not dominate the load, we cannot do anything...
- if (!DomSetInfo.dominates(Store, Load))
- return false;
-
- BasicBlock *BB1 = Store->getParent(), *BB2 = Load->getParent();
- Value *LoadAddress = Load->getOperand(0);
-
- assert(LoadAddress->getType() == Store->getOperand(1)->getType() &&
- "How could the same source pointer return different types?");
+ // Figure out if the load is invalidated between the load and the exit of the
+ // block it is defined in. While we are scanning the current basic block, if
+ // we see any candidate loads, then we know they have the same value # as LI.
+ //
+ bool LoadInvalidatedInBBAfter = false;
+ for (BasicBlock::iterator I = LI->getNext(); I != LoadBB->end(); ++I) {
+ // If this instruction is a load, then this instruction returns the same
+ // value as LI.
+ if (isa<LoadInst>(I) && Instrs.count(I)) {
+ RetVals.push_back(I);
+ Instrs.erase(I);
+ }
- // Find out how many bytes of memory are loaded by the load instruction...
- unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(Load->getType());
+ if (AA.getModRefInfo(I, LoadPtr, LoadSize) & AliasAnalysis::Mod) {
+ LoadInvalidatedInBBAfter = true;
+ break;
+ }
+ }
- // Compute a basic block iterator pointing to the instruction after the store.
- BasicBlock::iterator StoreIt = Store; ++StoreIt;
+ // If there is anything left in the Instrs set, it could not possibly equal
+ // LI.
+ Instrs.clear();
+
+ // TransparentBlocks - For each basic block the load/store is alive across,
+ // figure out if the pointer is invalidated or not. If it is invalidated, the
+ // boolean is set to false, if it's not it is set to true. If we don't know
+ // yet, the entry is not in the map.
+ std::map<BasicBlock*, bool> TransparentBlocks;
+
+ // Loop over all of the basic blocks that also load the value. If the value
+ // is live across the CFG from the source to destination blocks, and if the
+ // value is not invalidated in either the source or destination blocks, add it
+ // to the equivalence sets.
+ for (std::map<BasicBlock*, std::vector<LoadInst*> >::iterator
+ I = CandidateLoads.begin(), E = CandidateLoads.end(); I != E; ++I) {
+ bool CantEqual = false;
+
+ // Right now we only can handle cases where one load dominates the other.
+ // FIXME: generalize this!
+ BasicBlock *BB1 = I->first, *BB2 = LoadBB;
+ if (DomSetInfo.dominates(BB1, BB2)) {
+ // The other load dominates LI. If the loaded value is killed entering
+ // the LoadBB block, we know the load is not live.
+ if (LoadInvalidatedInBBBefore)
+ CantEqual = true;
+ } else if (DomSetInfo.dominates(BB2, BB1)) {
+ std::swap(BB1, BB2); // Canonicalize
+ // LI dominates the other load. If the loaded value is killed exiting
+ // the LoadBB block, we know the load is not live.
+ if (LoadInvalidatedInBBAfter)
+ CantEqual = true;
+ } else {
+ // None of these loads can VN the same.
+ CantEqual = true;
+ }
- // Check to see if the intervening instructions between the two store and load
- // include a store or call...
- //
- if (BB1 == BB2) { // In same basic block?
- // In this degenerate case, no checking of global basic blocks has to occur
- // just check the instructions BETWEEN Store & Load...
- //
- if (AA.canInstructionRangeModify(*StoreIt, *Load, LoadAddress, LoadSize))
- return false; // Cannot eliminate load
+ if (!CantEqual) {
+ // Ok, at this point, we know that BB1 dominates BB2, and that there is
+ // nothing in the LI block that kills the loaded value. Check to see if
+ // the value is live across the CFG.
+ std::set<BasicBlock*> Visited;
+ for (pred_iterator PI = pred_begin(BB2), E = pred_end(BB2); PI!=E; ++PI)
+ if (!isPathTransparentTo(*PI, BB1, LoadPtr, LoadSize, AA,
+ Visited, TransparentBlocks)) {
+ // None of these loads can VN the same.
+ CantEqual = true;
+ break;
+ }
+ }
- // No instructions invalidate the stored value, they produce the same value!
- return true;
- } else {
- // Make sure that there are no store instructions between the Store and the
- // end of its basic block...
- //
- if (AA.canInstructionRangeModify(*StoreIt, *BB1->getTerminator(),
- LoadAddress, LoadSize))
- return false; // Cannot eliminate load
-
- // Make sure that there are no store instructions between the start of BB2
- // and the second load instruction...
- //
- if (AA.canInstructionRangeModify(BB2->front(), *Load, LoadAddress,LoadSize))
- return false; // Cannot eliminate load
-
- // Do a depth first traversal of the inverse CFG starting at L2's block,
- // looking for L1's block. The inverse CFG is made up of the predecessor
- // nodes of a block... so all of the edges in the graph are "backward".
- //
- std::set<BasicBlock*> VisitedSet;
- for (pred_iterator PI = pred_begin(BB2), PE = pred_end(BB2); PI != PE; ++PI)
- if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, LoadSize, AA,
- VisitedSet))
- return false;
+ // If the loads can equal so far, scan the basic block that contains the
+ // loads under consideration to see if they are invalidated in the block.
+ // For any loads that are not invalidated, add them to the equivalence
+ // set!
+ if (!CantEqual) {
+ Instrs.insert(I->second.begin(), I->second.end());
+ if (BB1 == LoadBB) {
+ // If LI dominates the block in question, check to see if any of the
+ // loads in this block are invalidated before they are reached.
+ for (BasicBlock::iterator BBI = I->first->begin(); ; ++BBI) {
+ if (isa<LoadInst>(BBI) && Instrs.count(BBI)) {
+ // The load is in the set!
+ RetVals.push_back(BBI);
+ Instrs.erase(BBI);
+ if (Instrs.empty()) break;
+ } else if (AA.getModRefInfo(BBI, LoadPtr, LoadSize)
+ & AliasAnalysis::Mod) {
+ // If there is a modifying instruction, nothing below it will value
+ // # the same.
+ break;
+ }
+ }
+ } else {
+ // If the block dominates LI, make sure that the loads in the block are
+ // not invalidated before the block ends.
+ BasicBlock::iterator BBI = I->first->end();
+ while (1) {
+ --BBI;
+ if (isa<LoadInst>(BBI) && Instrs.count(BBI)) {
+ // The load is in the set!
+ RetVals.push_back(BBI);
+ Instrs.erase(BBI);
+ if (Instrs.empty()) break;
+ } else if (AA.getModRefInfo(BBI, LoadPtr, LoadSize)
+ & AliasAnalysis::Mod) {
+ // If there is a modifying instruction, nothing above it will value
+ // # the same.
+ break;
+ }
+ }
+ }
- // If we passed all of these checks then we are sure that the two loads
- // produce the same value.
- return true;
+ Instrs.clear();
+ }
}
-}
-} // End llvm namespace
+ // Handle candidate stores. If the loaded location is clobbered on entrance
+ // to the LoadBB, no store outside of the LoadBB can value number equal, so
+ // quick exit.
+ if (LoadInvalidatedInBBBefore)
+ return;
+
+ for (std::map<BasicBlock*, std::vector<StoreInst*> >::iterator
+ I = CandidateStores.begin(), E = CandidateStores.end(); I != E; ++I)
+ if (DomSetInfo.dominates(I->first, LoadBB)) {
+ // Check to see if the path from the store to the load is transparent
+ // w.r.t. the memory location.
+ bool CantEqual = false;
+ std::set<BasicBlock*> Visited;
+ for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB);
+ PI != E; ++PI)
+ if (!isPathTransparentTo(*PI, I->first, LoadPtr, LoadSize, AA,
+ Visited, TransparentBlocks)) {
+ // None of these stores can VN the same.
+ CantEqual = true;
+ break;
+ }
+ Visited.clear();
+ if (!CantEqual) {
+ // Okay, the path from the store block to the load block is clear, and
+ // we know that there are no invalidating instructions from the start
+ // of the load block to the load itself. Now we just scan the store
+ // block.
+
+ BasicBlock::iterator BBI = I->first->end();
+ while (1) {
+ --BBI;
+ if (AA.getModRefInfo(BBI, LoadPtr, LoadSize)& AliasAnalysis::Mod){
+ // If the invalidating instruction is one of the candidates,
+ // then it provides the value the load loads.
+ if (StoreInst *SI = dyn_cast<StoreInst>(BBI))
+ if (std::find(I->second.begin(), I->second.end(), SI) !=
+ I->second.end())
+ RetVals.push_back(SI->getOperand(0));
+ break;
+ }
+ }
+ }
+ }
+}
Index: llvm/lib/Analysis/LoopInfo.cpp
diff -u llvm/lib/Analysis/LoopInfo.cpp:1.46 llvm/lib/Analysis/LoopInfo.cpp:1.46.2.1
--- llvm/lib/Analysis/LoopInfo.cpp:1.46 Wed Jan 7 18:09:01 2004
+++ llvm/lib/Analysis/LoopInfo.cpp Mon Mar 1 17:58:12 2004
@@ -14,10 +14,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/Dominators.h"
-#include "llvm/Support/CFG.h"
+#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Assembly/Writer.h"
+#include "llvm/Support/CFG.h"
#include "Support/DepthFirstIterator.h"
#include <algorithm>
Index: llvm/lib/Analysis/ValueNumbering.cpp
diff -u llvm/lib/Analysis/ValueNumbering.cpp:1.9 llvm/lib/Analysis/ValueNumbering.cpp:1.9.4.1
--- llvm/lib/Analysis/ValueNumbering.cpp:1.9 Wed Dec 10 23:05:56 2003
+++ llvm/lib/Analysis/ValueNumbering.cpp Mon Mar 1 17:58:12 2004
@@ -15,9 +15,9 @@
#include "llvm/Analysis/ValueNumbering.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/BasicBlock.h"
+#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Type.h"
-#include "llvm/iMemory.h"
namespace llvm {
@@ -104,17 +104,14 @@
for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
UI != UE; ++UI)
- if (Instruction *Other = dyn_cast<Instruction>(*UI))
- // Check to see if this new cast is not I, but has the same operand...
- if (Other != &I && Other->getOpcode() == I.getOpcode() &&
- Other->getOperand(0) == Op && // Is the operand the same?
+ if (CastInst *Other = dyn_cast<CastInst>(*UI))
+ // Check that the types are the same, since this code handles casts...
+ if (Other->getType() == I.getType() &&
// Is it embedded in the same function? (This could be false if LHS
// is a constant or global!)
Other->getParent()->getParent() == F &&
-
- // Check that the types are the same, since this code handles casts...
- Other->getType() == I.getType()) {
-
+ // Check to see if this new cast is not I.
+ Other != &I) {
// These instructions are identical. Add to list...
RetVals.push_back(Other);
}
More information about the llvm-commits
mailing list