From lattner at cs.uiuc.edu Mon Feb 24 14:09:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:09:01 2003 Subject: [llvm-commits] CVS: llvm/tools/analyze/analyze.cpp Message-ID: <200302242008.OAA16513@apoc.cs.uiuc.edu> Changes in directory llvm/tools/analyze: analyze.cpp updated: 1.49 -> 1.50 --- Log message: Make printing messages nicer --- Diffs of the changes: Index: llvm/tools/analyze/analyze.cpp diff -u llvm/tools/analyze/analyze.cpp:1.49 llvm/tools/analyze/analyze.cpp:1.50 --- llvm/tools/analyze/analyze.cpp:1.49 Tue Dec 3 13:42:26 2002 +++ llvm/tools/analyze/analyze.cpp Mon Feb 24 14:07:54 2003 @@ -25,8 +25,7 @@ ModulePassPrinter(const PassInfo *PI) : PassToPrint(PI) {} virtual bool run(Module &M) { - std::cout << "Printing Analysis info for Pass " - << PassToPrint->getPassName() << ":\n"; + std::cout << "Printing analysis '" << PassToPrint->getPassName() << "':\n"; getAnalysisID(PassToPrint).print(std::cout, &M); // Get and print pass... @@ -46,8 +45,8 @@ FunctionPassPrinter(const PassInfo *PI) : PassToPrint(PI) {} virtual bool runOnFunction(Function &F) { - std::cout << "Printing Analysis info for function '" << F.getName() - << "': Pass " << PassToPrint->getPassName() << ":\n"; + std::cout << "Printing analysis '" << PassToPrint->getPassName() + << "' for function '" << F.getName() << "':\n"; getAnalysisID(PassToPrint).print(std::cout, F.getParent()); // Get and print pass... From lattner at cs.uiuc.edu Mon Feb 24 14:31:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:31:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll Message-ID: <200302242030.OAA16834@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/DSGraphAA: gcsetest.ll updated: 1.2 -> 1.3 --- Log message: Fix test --- Diffs of the changes: Index: llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll diff -u llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll:1.2 llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll:1.3 --- llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll:1.2 Mon Feb 3 15:40:14 2003 +++ llvm/test/Regression/Transforms/DSGraphAA/gcsetest.ll Mon Feb 24 14:30:14 2003 @@ -38,11 +38,11 @@ %B = call int* %getp(%intpair* %C) %A1 = load int* %A - store int 123, int* %B ; Store cannot alias %A + store int 123, int* %B ; Store does alias %A %A2 = load int* %A - %ELIM_x = sub int %A1, %A2 - ret int %ELIM_x + %x = sub int %A1, %A2 + ret int %x } int %test2() { ; Test context sensitivity From lattner at cs.uiuc.edu Mon Feb 24 14:36:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:36:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Support/CallSite.h Message-ID: <200302242035.OAA16977@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: CallSite.h added (r1.1) --- Log message: Initial checkin of CallSite wrapper for Call/Invoke instructions --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Feb 24 14:39:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:39:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/AliasSetTracker.h Message-ID: <200302242038.OAA17062@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: AliasSetTracker.h updated: 1.1 -> 1.2 --- Log message: This is a substantial rewrite of the AliasSetTracker class which now uses a union-find based algorithm, is significantly faster, and is more general. It will also scale to handle call instructions correctly, which is a nice added bonus. This includes a new pass -print-alias-sets which can be used to show how alias sets are formed for a particular analysis. --- Diffs of the changes: Index: llvm/include/llvm/Analysis/AliasSetTracker.h diff -u llvm/include/llvm/Analysis/AliasSetTracker.h:1.1 llvm/include/llvm/Analysis/AliasSetTracker.h:1.2 --- llvm/include/llvm/Analysis/AliasSetTracker.h:1.1 Thu Sep 26 16:49:04 2002 +++ llvm/include/llvm/Analysis/AliasSetTracker.h Mon Feb 24 14:37:52 2003 @@ -10,80 +10,194 @@ #ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H #define LLVM_ANALYSIS_ALIASSETTRACKER_H -#include +#include "llvm/Support/CallSite.h" +#include "Support/iterator" +#include "Support/hash_map" +#include "Support/ilist" class AliasAnalysis; class LoadInst; class StoreInst; -class CallInst; -class InvokeInst; -class Value; class AliasSetTracker; +class AliasSet; class AliasSet { friend class AliasSetTracker; - std::vector Loads; - std::vector Stores; - std::vector Calls; - std::vector Invokes; -public: + + struct PointerRec; + typedef std::pair HashNodePair; + + class PointerRec { + HashNodePair *NextInList; + AliasSet *AS; + public: + PointerRec() : NextInList(0), AS(0) {} + + HashNodePair *getNext() const { return NextInList; } + bool hasAliasSet() const { return AS != 0; } + + AliasSet *getAliasSet(AliasSetTracker &AST) { + assert(AS && "No AliasSet yet!"); + if (AS->Forward) { + AliasSet *OldAS = AS; + AS = OldAS->getForwardedTarget(AST); + if (--OldAS->RefCount == 0) + OldAS->removeFromTracker(AST); + AS->RefCount++; + } + return AS; + } + + void setAliasSet(AliasSet *as) { + assert(AS == 0 && "Already have an alias set!"); + AS = as; + } + void setTail(HashNodePair *T) { + assert(NextInList == 0 && "Already have tail!"); + NextInList = T; + } + }; + + HashNodePair *PtrListHead, *PtrListTail; // Singly linked list of nodes + AliasSet *Forward; // Forwarding pointer + AliasSet *Next, *Prev; // Doubly linked list of AliasSets + + std::vector CallSites; // All calls & invokes in this node + + // RefCount - Number of nodes pointing to this AliasSet plus the number of + // AliasSets forwarding to it. + unsigned RefCount : 29; + /// AccessType - Keep track of whether this alias set merely refers to the /// locations of memory, whether it modifies the memory, or whether it does - /// both. The lattice goes from "None" (alias set not present) to either Refs - /// or Mods, then to ModRef as neccesary. + /// both. The lattice goes from "NoModRef" to either Refs or Mods, then to + /// ModRef as neccesary. /// enum AccessType { - Refs, Mods, ModRef + NoModRef = 0, Refs = 1, // Ref = bit 1 + Mods = 2, ModRef = 3 // Mod = bit 2 }; + unsigned AccessTy : 2; /// AliasType - Keep track the relationships between the pointers in the set. /// Lattice goes from MustAlias to MayAlias. /// enum AliasType { - MustAlias, MayAlias + MustAlias = 0, MayAlias = 1 }; -private: - enum AccessType AccessTy; - enum AliasType AliasTy; -public: - /// Accessors... - enum AccessType getAccessType() const { return AccessTy; } - enum AliasType getAliasType() const { return AliasTy; } + unsigned AliasTy : 1; - // TODO: in the future, add a fixed size (4? 2?) cache of pointers that we - // know are in the alias set, to cut down time answering "pointeraliasesset" - // queries. + /// Define an iterator for alias sets... this is just a forward iterator. + class iterator : public forward_iterator { + HashNodePair *CurNode; + public: + iterator(HashNodePair *CN = 0) : CurNode(CN) {} + + bool operator==(const iterator& x) const { + return CurNode == x.CurNode; + } + bool operator!=(const iterator& x) const { return !operator==(x); } + + const iterator &operator=(const iterator &I) { + CurNode = I.CurNode; + return *this; + } + + value_type operator*() const { + assert(CurNode && "Dereferencing AliasSet.end()!"); + return CurNode->first; + } + value_type operator->() const { return operator*(); } + + iterator& operator++() { // Preincrement + assert(CurNode && "Advancing past AliasSet.end()!"); + CurNode = CurNode->second.getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; ++*this; return tmp; + } + }; - /// pointerAliasesSet - Return true if the specified pointer "may" (or must) - /// alias one of the members in the set. - /// - bool pointerAliasesSet(const Value *Ptr, AliasAnalysis &AA) const; + friend class ilist_traits; + AliasSet *getPrev() const { return Prev; } + AliasSet *getNext() const { return Next; } + void setPrev(AliasSet *P) { Prev = P; } + void setNext(AliasSet *N) { Next = N; } + +public: + /// Accessors... + bool isRef() const { return AccessTy & Refs; } + bool isMod() const { return AccessTy & Mods; } + bool isMustAlias() const { return AliasTy == MustAlias; } + bool isMayAlias() const { return AliasTy == MayAlias; } /// mergeSetIn - Merge the specified alias set into this alias set... /// - void mergeSetIn(const AliasSet &AS); + void mergeSetIn(AliasSet &AS); - const std::vector &getLoads() const { return Loads; } - const std::vector &getStores() const { return Stores; } - const std::vector &getCalls() const { return Calls; } - const std::vector &getInvokes() const { return Invokes; } + // Alias Set iteration - Allow access to all of the pointer which are part of + // this alias set... + iterator begin() const { return iterator(PtrListHead); } + iterator end() const { return iterator(); } + + void print(std::ostream &OS) const; + void dump() const; private: - AliasSet() : AliasTy(MustAlias) {} // Can only be created by AliasSetTracker - void updateAccessType(); - Value *getSomePointer() const; + // Can only be created by AliasSetTracker + AliasSet() : PtrListHead(0), PtrListTail(0), Forward(0), RefCount(0), + AccessTy(NoModRef), AliasTy(MustAlias) { + } + Value *getSomePointer() const { + return PtrListHead ? PtrListHead->first : 0; + } + + /// getForwardedTarget - Return the real alias set this represents. If this + /// has been merged with another set and is forwarding, return the ultimate + /// destination set. This also implements the union-find collapsing as well. + AliasSet *getForwardedTarget(AliasSetTracker &AST) { + if (!Forward) return this; + + AliasSet *Dest = Forward->getForwardedTarget(AST); + if (Dest != Forward) { + Dest->RefCount++; + if (--Forward->RefCount == 0) + Forward->removeFromTracker(AST); + Forward = Dest; + } + return Dest; + } + + void removeFromTracker(AliasSetTracker &AST); + + void addPointer(AliasSetTracker &AST, HashNodePair &Entry); + void addCallSite(CallSite CS); + + /// aliasesPointer - Return true if the specified pointer "may" (or must) + /// alias one of the members in the set. + /// + bool aliasesPointer(const Value *Ptr, AliasAnalysis &AA) const; + bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; }; +inline std::ostream& operator<<(std::ostream &OS, const AliasSet &AS) { + AS.print(OS); + return OS; +} + class AliasSetTracker { AliasAnalysis &AA; - std::vector AliasSets; + ilist AliasSets; + + // Map from pointers to their node + hash_map PointerMap; public: /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use /// the specified alias analysis object to disambiguate load and store /// addresses. AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} - /// add methods - These methods are used to add different types of /// instructions to the alias sets. Adding a new instruction can result in /// one of three actions happening: @@ -95,15 +209,57 @@ /// void add(LoadInst *LI); void add(StoreInst *SI); - void add(CallInst *CI); - void add(InvokeInst *II); + void add(CallSite CS); // Call/Invoke instructions + void add(CallInst *CI) { add(CallSite(CI)); } + void add(InvokeInst *II) { add(CallSite(II)); } + void add(Instruction *I); // Dispatch to one of the other add methods... /// getAliasSets - Return the alias sets that are active. - const std::vector &getAliasSets() const { return AliasSets; } + const ilist &getAliasSets() const { return AliasSets; } + + /// getAliasSetForPointer - Return the alias set that the specified pointer + /// lives in... + AliasSet &getAliasSetForPointer(Value *P); + + /// getAliasAnalysis - Return the underlying alias analysis object used by + /// this tracker. + AliasAnalysis &getAliasAnalysis() const { return AA; } + + typedef ilist::iterator iterator; + typedef ilist::const_iterator const_iterator; + + const_iterator begin() const { return AliasSets.begin(); } + const_iterator end() const { return AliasSets.end(); } + + iterator begin() { return AliasSets.begin(); } + iterator end() { return AliasSets.end(); } + + void print(std::ostream &OS) const; + void dump() const; private: + friend class AliasSet; + void removeAliasSet(AliasSet *AS); + + AliasSet::HashNodePair &getEntryFor(Value *V) { + // Standard operator[], except that it returns the whole pair, not just + // ->second. + return *PointerMap.insert(AliasSet::HashNodePair(V, + AliasSet::PointerRec())).first; + } + + void addPointer(Value *P, AliasSet::AccessType E) { + AliasSet &AS = getAliasSetForPointer(P); + AS.AccessTy |= E; + } AliasSet *findAliasSetForPointer(const Value *Ptr); - void mergeAllSets(); + + AliasSet *findAliasSetForCallSite(CallSite CS); }; + +inline std::ostream& operator<<(std::ostream &OS, const AliasSetTracker &AST) { + AST.print(OS); + return OS; +} #endif From lattner at cs.uiuc.edu Mon Feb 24 14:39:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:39:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasSetTracker.cpp Message-ID: <200302242038.OAA17069@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasSetTracker.cpp updated: 1.1 -> 1.2 --- Log message: This is a substantial rewrite of the AliasSetTracker class which now uses a union-find based algorithm, is significantly faster, and is more general. It will also scale to handle call instructions correctly, which is a nice added bonus. This includes a new pass -print-alias-sets which can be used to show how alias sets are formed for a particular analysis. --- Diffs of the changes: Index: llvm/lib/Analysis/AliasSetTracker.cpp diff -u llvm/lib/Analysis/AliasSetTracker.cpp:1.1 llvm/lib/Analysis/AliasSetTracker.cpp:1.2 --- llvm/lib/Analysis/AliasSetTracker.cpp:1.1 Thu Sep 26 16:49:07 2002 +++ llvm/lib/Analysis/AliasSetTracker.cpp Mon Feb 24 14:37:56 2003 @@ -9,164 +9,271 @@ #include "llvm/iMemory.h" #include "llvm/iOther.h" #include "llvm/iTerminators.h" +#include "llvm/Pass.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/InstIterator.h" -/// updateAccessTypes - Depending on what type of accesses are in this set, -/// decide whether the set contains just references, just modifications, or a -/// mix. +/// mergeSetIn - Merge the specified alias set into this alias set... /// -void AliasSet::updateAccessType() { - if (!Calls.empty() || !Invokes.empty()) { - AccessTy = ModRef; - } else if (!Loads.empty()) { - if (Stores.empty()) - AccessTy = Refs; - else - AccessTy = ModRef; - } else { - AccessTy = Mods; +void AliasSet::mergeSetIn(AliasSet &AS) { + assert(!AS.Forward && "Alias set is already forwarding!"); + assert(!Forward && "This set is a forwarding set!!"); + + // Update the alias and access types of this set... + AccessTy |= AS.AccessTy; + AliasTy |= AS.AliasTy; + + if (CallSites.empty()) { // Merge call sites... + if (!AS.CallSites.empty()) + std::swap(CallSites, AS.CallSites); + } else if (!AS.CallSites.empty()) { + CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end()); + AS.CallSites.clear(); } + + // FIXME: If AS's refcount is zero, nuke it now... + assert(RefCount != 0); + + AS.Forward = this; // Forward across AS now... + RefCount++; // AS is now pointing to us... + + // Merge the list of constituent pointers... + PtrListTail->second.setTail(AS.PtrListHead); + PtrListTail = AS.PtrListTail; + AS.PtrListHead = AS.PtrListTail = 0; } -/// mergeSetIn - Merge the specified alias set into this alias set... -/// -void AliasSet::mergeSetIn(const AliasSet &AS) { - // Merge instruction sets... - Loads.insert( Loads.end(), AS.Loads.begin() , AS.Loads.end()); - Stores.insert( Stores.end(), AS.Stores.begin() , AS.Stores.end()); - Calls.insert( Calls.end(), AS.Calls.begin() , AS.Calls.end()); - Invokes.insert(Invokes.end(), AS.Invokes.begin(), AS.Invokes.end()); +void AliasSetTracker::removeAliasSet(AliasSet *AS) { + AliasSets.erase(AS); +} - // Update the alias and access types of this set... - if (AS.getAliasType() == MayAlias) - AliasTy = MayAlias; - updateAccessType(); +void AliasSet::removeFromTracker(AliasSetTracker &AST) { + assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); + AST.removeAliasSet(this); +} + +void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry){ + assert(!Entry.second.hasAliasSet() && "Entry already in set!"); + + AliasAnalysis &AA = AST.getAliasAnalysis(); + + if (isMustAlias()) // Check to see if we have to downgrade to _may_ alias + if (Value *V = getSomePointer()) + if (AA.alias(V, Entry.first) == AliasAnalysis::MayAlias) + AliasTy = MayAlias; + + Entry.second.setAliasSet(this); + + // Add it to the end of the list... + if (PtrListTail) + PtrListTail->second.setTail(&Entry); + else + PtrListHead = &Entry; + PtrListTail = &Entry; + RefCount++; // Entry points to alias set... +} + +void AliasSet::addCallSite(CallSite CS) { + CallSites.push_back(CS); + AliasTy = MayAlias; // FIXME: Too conservative } -/// pointerAliasesSet - Return true if the specified pointer "may" (or must) +/// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// -bool AliasSet::pointerAliasesSet(const Value *Ptr, AliasAnalysis &AA) const { - if (!Calls.empty() || !Invokes.empty()) - return true; - for (unsigned i = 0, e = Loads.size(); i != e; ++i) - if (AA.alias(Ptr, Loads[i]->getOperand(0))) - return true; - for (unsigned i = 0, e = Stores.size(); i != e; ++i) - if (AA.alias(Ptr, Stores[i]->getOperand(1))) +bool AliasSet::aliasesPointer(const Value *Ptr, AliasAnalysis &AA) const { + if (AliasTy == MustAlias) { + assert(CallSites.empty() && "Illegal must alias set!"); + + // If this is a set of MustAliases, only check to see if the pointer aliases + // SOME value in the set... + Value *SomePtr = getSomePointer(); + assert(SomePtr && "Empty must-alias set??"); + return AA.alias(SomePtr, Ptr); + } + + // If this is a may-alias set, we have to check all of the pointers in the set + // to be sure it doesn't alias the set... + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.alias(Ptr, *I)) return true; + + // Check the call sites list and invoke list... + if (!CallSites.empty()) + // FIXME: this is pessimistic! + return true; + return false; } -/// getSomePointer - This method may only be called when the AliasType of the -/// set is MustAlias. This is used to return any old pointer (which must alias -/// all other pointers in the set) so that the caller can decide whether to turn -/// this set into a may alias set or not. -/// -Value *AliasSet::getSomePointer() const { - assert(getAliasType() == MustAlias && - "Cannot call getSomePointer on a 'MayAlias' set!"); - assert(Calls.empty() && Invokes.empty() && "Call/invokes mean may alias!"); - - if (!Loads.empty()) - return Loads[0]->getOperand(0); - assert(!Stores.empty() && "There are no instructions in this set!"); - return Stores[0]->getOperand(1); +bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { + // FIXME: Too conservative! + return true; } - /// findAliasSetForPointer - Given a pointer, find the one alias set to put the /// instruction referring to the pointer into. If there are multiple alias sets /// that may alias the pointer, merge them together and return the unified set. /// AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr) { AliasSet *FoundSet = 0; - for (unsigned i = 0; i != AliasSets.size(); ++i) { - if (AliasSets[i].pointerAliasesSet(Ptr, AA)) { + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->aliasesPointer(Ptr, AA)) { if (FoundSet == 0) { // If this is the first alias set ptr can go into... - FoundSet = &AliasSets[i]; // Remember it. + FoundSet = I; // Remember it. } else { // Otherwise, we must merge the sets... - FoundSet->mergeSetIn(AliasSets[i]); // Merge in contents... - AliasSets.erase(AliasSets.begin()+i); // Remove the set... - --i; // Don't skip the next set + FoundSet->mergeSetIn(*I); // Merge in contents... + } + } + + return FoundSet; +} + +AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->aliasesCallSite(CS, AA)) { + if (FoundSet == 0) { // If this is the first alias set ptr can go into... + FoundSet = I; // Remember it. + } else { // Otherwise, we must merge the sets... + FoundSet->mergeSetIn(*I); // Merge in contents... } } - } return FoundSet; } -void AliasSetTracker::add(LoadInst *LI) { - Value *Pointer = LI->getOperand(0); - // Check to see if the loaded pointer aliases any sets... - AliasSet *AS = findAliasSetForPointer(Pointer); - if (AS) { - AS->Loads.push_back(LI); - // Check to see if we need to change this into a MayAlias set now... - if (AS->getAliasType() == AliasSet::MustAlias) - if (AA.alias(AS->getSomePointer(), Pointer) != AliasAnalysis::MustAlias) - AS->AliasTy = AliasSet::MayAlias; - AS->updateAccessType(); + +/// getAliasSetForPointer - Return the alias set that the specified pointer +/// lives in... +AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer) { + AliasSet::HashNodePair &Entry = getEntryFor(Pointer); + + // Check to see if the pointer is already known... + if (Entry.second.hasAliasSet()) { + // Return the set! + return *Entry.second.getAliasSet(*this)->getForwardedTarget(*this); + } else if (AliasSet *AS = findAliasSetForPointer(Pointer)) { + // Add it to the alias set it aliases... + AS->addPointer(*this, Entry); + return *AS; } else { - // Otherwise create a new alias set to hold the load... + // Otherwise create a new alias set to hold the loaded pointer... AliasSets.push_back(AliasSet()); - AliasSets.back().Loads.push_back(LI); - AliasSets.back().AccessTy = AliasSet::Refs; + AliasSets.back().addPointer(*this, Entry); + return AliasSets.back(); } } +void AliasSetTracker::add(LoadInst *LI) { + addPointer(LI->getOperand(0), AliasSet::Refs); +} + void AliasSetTracker::add(StoreInst *SI) { - Value *Pointer = SI->getOperand(1); + addPointer(SI->getOperand(1), AliasSet::Mods); +} - // Check to see if the loaded pointer aliases any sets... - AliasSet *AS = findAliasSetForPointer(Pointer); - if (AS) { - AS->Stores.push_back(SI); - // Check to see if we need to change this into a MayAlias set now... - if (AS->getAliasType() == AliasSet::MustAlias) - if (AA.alias(AS->getSomePointer(), Pointer) != AliasAnalysis::MustAlias) - AS->AliasTy = AliasSet::MayAlias; - AS->updateAccessType(); - } else { - // Otherwise create a new alias set to hold the load... +void AliasSetTracker::add(CallSite CS) { + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) { AliasSets.push_back(AliasSet()); - AliasSets.back().Stores.push_back(SI); - AliasSets.back().AccessTy = AliasSet::Mods; + AS = &AliasSets.back(); } + AS->addCallSite(CS); } +void AliasSetTracker::add(Instruction *I) { + // Dispatch to one of the other add methods... + if (LoadInst *LI = dyn_cast(I)) + add(LI); + else if (StoreInst *SI = dyn_cast(I)) + add(SI); + else if (CallInst *CI = dyn_cast(I)) + add(CI); + else if (InvokeInst *II = dyn_cast(I)) + add(II); +} -void AliasSetTracker::mergeAllSets() { - if (AliasSets.size() < 2) return; // Noop +//===----------------------------------------------------------------------===// +// AliasSet/AliasSetTracker Printing Support +//===----------------------------------------------------------------------===// + +void AliasSet::print(std::ostream &OS) const { + OS << " AliasSet[" << (void*)this << "," << RefCount << "] "; + OS << (AliasTy == MustAlias ? "must" : "may ") << " alias, "; + switch (AccessTy) { + case NoModRef: OS << "No access "; break; + case Refs : OS << "Ref "; break; + case Mods : OS << "Mod "; break; + case ModRef : OS << "Mod/Ref "; break; + default: assert(0 && "Bad value for AccessTy!"); + } + if (Forward) + OS << " forwarding to " << (void*)Forward; - // Merge all of the sets into set #0 - for (unsigned i = 1, e = AliasSets.size(); i != e; ++i) - AliasSets[0].mergeSetIn(AliasSets[i]); - // Delete extraneous sets... - AliasSets.erase(AliasSets.begin()+1, AliasSets.end()); + if (begin() != end()) { + OS << "Pointers: "; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I != begin()) OS << ", "; + WriteAsOperand(OS, *I); + } + } + if (!CallSites.empty()) { + OS << "\n " << CallSites.size() << " Call Sites: "; + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (i) OS << ", "; + WriteAsOperand(OS, CallSites[i].getCalledValue()); + } + } + OS << "\n"; } -void AliasSetTracker::add(CallInst *CI) { - if (!AliasSets.empty()) { - mergeAllSets(); - } else { - AliasSets.push_back(AliasSet()); - } - AliasSets[0].AccessTy = AliasSet::ModRef; - AliasSets[0].AliasTy = AliasSet::MayAlias; - AliasSets[0].Calls.push_back(CI); +void AliasSetTracker::print(std::ostream &OS) const { + OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for " + << PointerMap.size() << " pointer values.\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) + I->print(OS); + OS << "\n"; } -void AliasSetTracker::add(InvokeInst *II) { - if (!AliasSets.empty()) { - mergeAllSets(); - } else { - AliasSets.push_back(AliasSet()); - } - AliasSets[0].AccessTy = AliasSet::ModRef; - AliasSets[0].AliasTy = AliasSet::MayAlias; - AliasSets[0].Invokes.push_back(II); +void AliasSet::dump() const { print (std::cerr); } +void AliasSetTracker::dump() const { print(std::cerr); } + + +//===----------------------------------------------------------------------===// +// AliasSetPrinter Pass +//===----------------------------------------------------------------------===// + +namespace { + class AliasSetPrinter : public FunctionPass { + AliasSetTracker *Tracker; + public: + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual bool runOnFunction(Function &F) { + Tracker = new AliasSetTracker(getAnalysis()); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + Tracker->add(*I); + return false; + } + + /// print - Convert to human readable form + virtual void print(std::ostream &OS) const { + Tracker->print(OS); + } + + virtual void releaseMemory() { + delete Tracker; + } + }; + RegisterPass X("print-alias-sets", "Alias Set Printer", + PassInfo::Analysis | PassInfo::Optimization); } From lattner at cs.uiuc.edu Mon Feb 24 14:49:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:49:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Instruction.h iMemory.h iOther.h iTerminators.h Message-ID: <200302242048.OAA17595@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Instruction.h updated: 1.36 -> 1.37 iMemory.h updated: 1.37 -> 1.38 iOther.h updated: 1.31 -> 1.32 iTerminators.h updated: 1.24 -> 1.25 --- Log message: Rename Instruction::hasSideEffects() -> mayWriteToMemory() --- Diffs of the changes: Index: llvm/include/llvm/Instruction.h diff -u llvm/include/llvm/Instruction.h:1.36 llvm/include/llvm/Instruction.h:1.37 --- llvm/include/llvm/Instruction.h:1.36 Wed Oct 30 22:13:59 2002 +++ llvm/include/llvm/Instruction.h Mon Feb 24 14:48:28 2003 @@ -55,7 +55,9 @@ Instruction *getPrev() { return Prev; } const Instruction *getPrev() const { return Prev; } - virtual bool hasSideEffects() const { return false; } // Memory & Call insts + /// mayWriteToMemory - Return true if this instruction may modify memory. + /// + virtual bool mayWriteToMemory() const { return false; } // --------------------------------------------------------------------------- /// Subclass classification... getOpcode() returns a member of Index: llvm/include/llvm/iMemory.h diff -u llvm/include/llvm/iMemory.h:1.37 llvm/include/llvm/iMemory.h:1.38 --- llvm/include/llvm/iMemory.h:1.37 Mon Sep 16 11:06:12 2002 +++ llvm/include/llvm/iMemory.h Mon Feb 24 14:48:28 2003 @@ -120,7 +120,7 @@ virtual Instruction *clone() const { return new FreeInst(Operands[0]); } - virtual bool hasSideEffects() const { return true; } + virtual bool mayWriteToMemory() const { return true; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const FreeInst *) { return true; } @@ -177,7 +177,7 @@ StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore = 0); virtual Instruction *clone() const { return new StoreInst(*this); } - virtual bool hasSideEffects() const { return true; } + virtual bool mayWriteToMemory() const { return true; } Value *getPointerOperand() { return getOperand(1); } const Value *getPointerOperand() const { return getOperand(1); } Index: llvm/include/llvm/iOther.h diff -u llvm/include/llvm/iOther.h:1.31 llvm/include/llvm/iOther.h:1.32 --- llvm/include/llvm/iOther.h:1.31 Fri Jan 31 18:41:27 2003 +++ llvm/include/llvm/iOther.h Mon Feb 24 14:48:28 2003 @@ -60,7 +60,7 @@ Instruction* InsertBefore = 0); virtual Instruction *clone() const { return new CallInst(*this); } - bool hasSideEffects() const { return true; } + bool mayWriteToMemory() const { return true; } const Function *getCalledFunction() const { return dyn_cast(Operands[0].get()); Index: llvm/include/llvm/iTerminators.h diff -u llvm/include/llvm/iTerminators.h:1.24 llvm/include/llvm/iTerminators.h:1.25 --- llvm/include/llvm/iTerminators.h:1.24 Tue Sep 10 18:54:56 2002 +++ llvm/include/llvm/iTerminators.h Mon Feb 24 14:48:28 2003 @@ -196,7 +196,7 @@ virtual Instruction *clone() const { return new InvokeInst(*this); } - bool hasSideEffects() const { return true; } + bool mayWriteToMemory() const { return true; } // getCalledFunction - Return the function called, or null if this is an // indirect function invocation... From lattner at cs.uiuc.edu Mon Feb 24 14:49:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:49:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ADCE.cpp Reassociate.cpp Message-ID: <200302242048.OAA17608@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ADCE.cpp updated: 1.49 -> 1.50 Reassociate.cpp updated: 1.15 -> 1.16 --- Log message: Rename Instruction::hasSideEffects() -> mayWriteToMemory() --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ADCE.cpp diff -u llvm/lib/Transforms/Scalar/ADCE.cpp:1.49 llvm/lib/Transforms/Scalar/ADCE.cpp:1.50 --- llvm/lib/Transforms/Scalar/ADCE.cpp:1.49 Wed Jan 22 20:12:18 2003 +++ llvm/lib/Transforms/Scalar/ADCE.cpp Mon Feb 24 14:48:30 2003 @@ -154,7 +154,7 @@ BBI != BBE; ++BBI) { BasicBlock *BB = *BBI; for (BasicBlock::iterator II = BB->begin(), EI = BB->end(); II != EI; ) { - if (II->hasSideEffects() || II->getOpcode() == Instruction::Ret) { + if (II->mayWriteToMemory() || II->getOpcode() == Instruction::Ret) { markInstructionLive(II); ++II; // Increment the inst iterator if the inst wasn't deleted } else if (isInstructionTriviallyDead(II)) { Index: llvm/lib/Transforms/Scalar/Reassociate.cpp diff -u llvm/lib/Transforms/Scalar/Reassociate.cpp:1.15 llvm/lib/Transforms/Scalar/Reassociate.cpp:1.16 --- llvm/lib/Transforms/Scalar/Reassociate.cpp:1.15 Sat Dec 14 21:56:00 2002 +++ llvm/lib/Transforms/Scalar/Reassociate.cpp Mon Feb 24 14:48:30 2003 @@ -74,7 +74,7 @@ if (I->getOpcode() == Instruction::PHINode || I->getOpcode() == Instruction::Alloca || I->getOpcode() == Instruction::Malloc || isa(I) || - I->hasSideEffects()) + I->mayWriteToMemory()) // Cannot move inst if it writes to memory! return RankMap[I->getParent()]; unsigned &CachedRank = InstRankMap[I]; From lattner at cs.uiuc.edu Mon Feb 24 14:49:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 14:49:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/Local.cpp Message-ID: <200302242048.OAA17615@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Local.cpp updated: 1.4 -> 1.5 --- Log message: Rename Instruction::hasSideEffects() -> mayWriteToMemory() --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/Local.cpp diff -u llvm/lib/Transforms/Utils/Local.cpp:1.4 llvm/lib/Transforms/Utils/Local.cpp:1.5 --- llvm/lib/Transforms/Utils/Local.cpp:1.4 Tue Jun 25 11:12:51 2002 +++ llvm/lib/Transforms/Utils/Local.cpp Mon Feb 24 14:48:32 2003 @@ -91,7 +91,7 @@ // bool isInstructionTriviallyDead(Instruction *I) { - return I->use_empty() && !I->hasSideEffects() && !isa(I); + return I->use_empty() && !I->mayWriteToMemory() && !isa(I); } // dceInstruction - Inspect the instruction at *BBI and figure out if it's From lattner at cs.uiuc.edu Mon Feb 24 17:15:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 17:15:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/licmtest.ll Message-ID: <200302242314.RAA22161@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: licmtest.ll updated: 1.3 -> 1.4 --- Log message: Fix testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/BasicAA/licmtest.ll diff -u llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.3 llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.4 --- llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.3 Sun Feb 23 21:52:13 2003 +++ llvm/test/Regression/Transforms/BasicAA/licmtest.ll Mon Feb 24 17:14:07 2003 @@ -4,7 +4,7 @@ ; not be able to eliminate the load itself, without licm's help. This is ; because, for GCSE, the load is killed by the dummy basic block. -; RUN: if as < %s | opt -basicaa -licm -gcse -simplifycfg -instcombine | dis | grep ToRemove +; RUN: if as < %s | opt -basicaa -licm -load-vn -gcse -instcombine | dis | grep ToRemove ; RUN: then exit 1 ; RUN: else exit 0 ; RUN: fi @@ -14,10 +14,10 @@ implementation int %test(bool %c) { - %ToRemove = load int* %A - br label %Loop -Loop: %Atmp = load int* %A + br bool %c, label %Dummy, label %Loop +Loop: + %ToRemove = load int* %A store int %Atmp, int* %B ; Store cannot alias %A br bool %c, label %Out, label %Loop From lattner at cs.uiuc.edu Mon Feb 24 18:02:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Feb 24 18:02:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/PassSupport.h Message-ID: <200302250001.SAA25615@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: PassSupport.h updated: 1.9 -> 1.10 --- Log message: Add new helper template function --- Diffs of the changes: Index: llvm/include/llvm/PassSupport.h diff -u llvm/include/llvm/PassSupport.h:1.9 llvm/include/llvm/PassSupport.h:1.10 --- llvm/include/llvm/PassSupport.h:1.9 Mon Sep 16 11:01:39 2002 +++ llvm/include/llvm/PassSupport.h Mon Feb 24 18:00:50 2003 @@ -171,6 +171,8 @@ template Pass *callDefaultCtor() { return new PassName(); } +template +Pass *callTargetDataCtor(const TargetData &TD) { return new PassName(TD); } template struct RegisterPass : public RegisterPassBase { From lattner at cs.uiuc.edu Tue Feb 25 14:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Feb 25 14:28:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/TargetData.cpp Message-ID: <200302252027.OAA04799@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target: TargetData.cpp updated: 1.26 -> 1.27 --- Log message: Remove wierd case that can never happen --- Diffs of the changes: Index: llvm/lib/Target/TargetData.cpp diff -u llvm/lib/Target/TargetData.cpp:1.26 llvm/lib/Target/TargetData.cpp:1.27 --- llvm/lib/Target/TargetData.cpp:1.26 Tue Oct 29 15:48:16 2002 +++ llvm/lib/Target/TargetData.cpp Tue Feb 25 14:27:09 2003 @@ -191,9 +191,6 @@ // Update Ty to refer to current element Ty = STy->getElementTypes()[FieldNo]; - - } else if (isa(Ty)) { - assert(0 && "Loading from arrays not implemented yet!"); } else { assert(0 && "Indexing type that is not struct or array?"); return 0; // Load directly through ptr From lattner at cs.uiuc.edu Tue Feb 25 15:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Feb 25 15:16:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Interpreter/Execution.cpp Message-ID: <200302252115.PAA04909@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/Interpreter: Execution.cpp updated: 1.75 -> 1.76 --- Log message: Fix typeo --- Diffs of the changes: Index: llvm/tools/lli/Interpreter/Execution.cpp diff -u llvm/tools/lli/Interpreter/Execution.cpp:1.75 llvm/tools/lli/Interpreter/Execution.cpp:1.76 --- llvm/tools/lli/Interpreter/Execution.cpp:1.75 Sun Jan 12 18:58:52 2003 +++ llvm/tools/lli/Interpreter/Execution.cpp Tue Feb 25 15:14:59 2003 @@ -698,7 +698,7 @@ Ty = STy->getElementTypes()[Index]; } else if (const SequentialType *ST = cast(Ty)) { - // Get the index number for the array... which must be uint type... + // Get the index number for the array... which must be long type... assert((*I)->getType() == Type::LongTy); unsigned Idx = getOperandValue(*I, SF).LongVal; if (const ArrayType *AT = dyn_cast(ST)) From lattner at cs.uiuc.edu Tue Feb 25 15:44:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Feb 25 15:44:04 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/featuretest.ll Message-ID: <200302252143.PAA05527@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: featuretest.ll updated: 1.3 -> 1.4 --- Log message: Add a new test for basicaa --- Diffs of the changes: Index: llvm/test/Regression/Transforms/BasicAA/featuretest.ll diff -u llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.3 llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.4 --- llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.3 Sun Feb 9 13:01:00 2003 +++ llvm/test/Regression/Transforms/BasicAA/featuretest.ll Tue Feb 25 15:43:37 2003 @@ -51,3 +51,14 @@ ret int %r } +; Test that if two pointers are spaced out by a constant offset, that they +; cannot alias, even if there is a variable offset between them... +int %gep_distance_test2({int,int}* %A, long %distance) { + %A = getelementptr {int,int}* %A, long 0, ubyte 0 + %REMOVEu = load int* %A + %B = getelementptr {int,int}* %A, long %distance, ubyte 1 + store int 7, int* %B ; B cannot alias A, it's at least 4 bytes away + %REMOVEv = load int* %A + %r = sub int %REMOVEu, %REMOVEv + ret int %r +} From lattner at cs.uiuc.edu Wed Feb 26 10:19:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 10:19:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/licmtest.ll Message-ID: <200302261618.KAA21443@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: licmtest.ll updated: 1.4 -> 1.5 --- Log message: Hopefully final tweak to this testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/BasicAA/licmtest.ll diff -u llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.4 llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.5 --- llvm/test/Regression/Transforms/BasicAA/licmtest.ll:1.4 Mon Feb 24 17:14:07 2003 +++ llvm/test/Regression/Transforms/BasicAA/licmtest.ll Wed Feb 26 10:18:00 2003 @@ -1,10 +1,9 @@ ; Test that LICM uses basicaa to do alias analysis, which is capable of -; disambiguating some obvious cases. The ToRemove load should be eliminated -; in this testcase. This testcase was carefully contrived so that GCSE would -; not be able to eliminate the load itself, without licm's help. This is -; because, for GCSE, the load is killed by the dummy basic block. +; disambiguating some obvious cases. If LICM is able to disambiguate the +; two pointers, then the load should be hoisted, and the store sunk. Thus +; the loop becomes empty and can be deleted by ADCE. -; RUN: if as < %s | opt -basicaa -licm -load-vn -gcse -instcombine | dis | grep ToRemove +; RUN: if as < %s | opt -basicaa -licm --adce | dis | grep Loop ; RUN: then exit 1 ; RUN: else exit 0 ; RUN: fi @@ -15,7 +14,7 @@ int %test(bool %c) { %Atmp = load int* %A - br bool %c, label %Dummy, label %Loop + br label %Loop Loop: %ToRemove = load int* %A store int %Atmp, int* %B ; Store cannot alias %A @@ -24,9 +23,5 @@ Out: %X = sub int %ToRemove, %Atmp ret int %X - -Dummy: - store int 7, int* %A - br label %Loop } From lattner at cs.uiuc.edu Wed Feb 26 10:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 10:39:01 2003 Subject: [llvm-commits] CVS: llvm/www/docs/ProgrammersManual.html Message-ID: <200302261638.KAA13090@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: ProgrammersManual.html updated: 1.37 -> 1.38 --- Log message: Update programmers manual for renamed method --- Diffs of the changes: Index: llvm/www/docs/ProgrammersManual.html diff -u llvm/www/docs/ProgrammersManual.html:1.37 llvm/www/docs/ProgrammersManual.html:1.38 --- llvm/www/docs/ProgrammersManual.html:1.37 Wed Nov 20 12:36:02 2002 +++ llvm/www/docs/ProgrammersManual.html Wed Feb 26 10:38:15 2003 @@ -1136,9 +1136,9 @@ Returns the BasicBlock that this Instruction is embedded into.

-

  • bool hasSideEffects()

    +

  • bool mayWriteToMemory()

    -Returns true if the instruction has side effects, i.e. it is a call, +Returns true if the instruction writes to memory, i.e. it is a call, free, invoke, or store.

  • unsigned getOpcode()

    @@ -1745,6 +1745,6 @@ Chris Lattner -Last modified: Wed Nov 20 12:21:34 CST 2002 +Last modified: Mon Feb 24 14:45:19 CST 2003 From lattner at cs.uiuc.edu Wed Feb 26 10:39:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 10:39:02 2003 Subject: [llvm-commits] CVS: llvm/www/docs/OpenProjects.html Message-ID: <200302261638.KAA13100@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: OpenProjects.html updated: 1.2 -> 1.3 --- Log message: Remove implemented projects --- Diffs of the changes: Index: llvm/www/docs/OpenProjects.html diff -u llvm/www/docs/OpenProjects.html:1.2 llvm/www/docs/OpenProjects.html:1.3 --- llvm/www/docs/OpenProjects.html:1.2 Fri Feb 7 13:25:35 2003 +++ llvm/www/docs/OpenProjects.html Wed Feb 26 10:38:22 2003 @@ -197,7 +197,6 @@

  • Implement alias analysis based optimizations:
    • Dead store elimination -
    • Location invariant Code Motion (LcICM)
    • Store+Reload or "store forwarding" elimination:

      Change:

      @@ -207,7 +206,6 @@
              
               store int X, int *P
               Y = X
      -
    • Register promotion (move loads and stores out of loop bodies, for example)
    @@ -287,6 +285,6 @@
    Chris Lattner
    -Last modified: Fri Feb 7 13:24:26 CST 2003 +Last modified: Wed Feb 26 10:37:31 CST 2003 From lattner at cs.uiuc.edu Wed Feb 26 13:11:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:11:02 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Pass.h Message-ID: <200302261910.NAA31457@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Pass.h updated: 1.29 -> 1.30 --- Log message: * Un "protect" the getAnalysis<> functions * Add a new initializePass() method to ImmutablePass --- Diffs of the changes: Index: llvm/include/llvm/Pass.h diff -u llvm/include/llvm/Pass.h:1.29 llvm/include/llvm/Pass.h:1.30 --- llvm/include/llvm/Pass.h:1.29 Wed Sep 25 16:59:09 2002 +++ llvm/include/llvm/Pass.h Wed Feb 26 13:10:28 2003 @@ -142,8 +142,6 @@ return dynamic_cast(Resolver->getAnalysisToUpdate(PI)); } -protected: - /// getAnalysis() - This function is used by subclasses to get /// to the analysis information that they claim to use by overriding the /// getAnalysisUsage function. @@ -203,8 +201,16 @@ /// "basic" versions of AnalysisGroups. /// struct ImmutablePass : public Pass { + /// initializePass - This method may be overriden by immutable passes to allow + /// them to perform various initialization actions they require. This is + /// primarily because an ImmutablePass can "require" another ImmutablePass, + /// and if it does, the overloaded version of initializePass may get access to + /// these passes with getAnalysis<>. + /// + virtual void initializePass() {} - // ImmutablePasses are never run. + /// ImmutablePasses are never run. + /// virtual bool run(Module &M) { return false; } private: From lattner at cs.uiuc.edu Wed Feb 26 13:12:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:12:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/PassManagerT.h Message-ID: <200302261911.NAA31472@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: PassManagerT.h updated: 1.36 -> 1.37 --- Log message: Allow ImmutablePass's to require other immutable passes and to be initialized --- Diffs of the changes: Index: llvm/lib/VMCore/PassManagerT.h diff -u llvm/lib/VMCore/PassManagerT.h:1.36 llvm/lib/VMCore/PassManagerT.h:1.37 --- llvm/lib/VMCore/PassManagerT.h:1.36 Thu Feb 13 23:34:36 2003 +++ llvm/lib/VMCore/PassManagerT.h Wed Feb 26 13:10:57 2003 @@ -530,7 +530,33 @@ // setAnalysisResolver(IP, this); ImmutablePasses.push_back(IP); + + // All Required analyses should be available to the pass as it initializes! + // Here we fill in the AnalysisImpls member of the pass so that it can + // successfully use the getAnalysis() method to retrieve the implementations + // it needs. + // + IP->AnalysisImpls.clear(); + IP->AnalysisImpls.reserve(AU.getRequiredSet().size()); + for (std::vector::const_iterator + I = AU.getRequiredSet().begin(), + E = AU.getRequiredSet().end(); I != E; ++I) { + Pass *Impl = getAnalysisOrNullUp(*I); + if (Impl == 0) { + std::cerr << "Analysis '" << (*I)->getPassName() + << "' used but not available!"; + assert(0 && "Analysis used but not available!"); + } else if (PassDebugging == Details) { + if ((*I)->getPassName() != std::string(Impl->getPassName())) + std::cerr << " Interface '" << (*I)->getPassName() + << "' implemented by '" << Impl->getPassName() << "'\n"; + } + IP->AnalysisImpls.push_back(std::make_pair(*I, Impl)); + } + // Initialize the immutable pass... + IP->initializePass(); + // Add this pass to the currently available set... if (const PassInfo *PI = IP->getPassInfo()) { CurrentAnalyses[PI] = IP; From lattner at cs.uiuc.edu Wed Feb 26 13:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:26:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/BasicAliasAnalysis.h Message-ID: <200302261925.NAA31517@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: BasicAliasAnalysis.h updated: 1.6 -> 1.7 --- Log message: Tweak to work with new AA implementation --- Diffs of the changes: Index: llvm/include/llvm/Analysis/BasicAliasAnalysis.h diff -u llvm/include/llvm/Analysis/BasicAliasAnalysis.h:1.6 llvm/include/llvm/Analysis/BasicAliasAnalysis.h:1.7 --- llvm/include/llvm/Analysis/BasicAliasAnalysis.h:1.6 Wed Nov 6 11:17:55 2002 +++ llvm/include/llvm/Analysis/BasicAliasAnalysis.h Wed Feb 26 13:25:04 2003 @@ -12,23 +12,26 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Pass.h" +class GetElementPtrInst; + struct BasicAliasAnalysis : public ImmutablePass, public AliasAnalysis { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + } + + virtual void initializePass(); + // alias - This is the only method here that does anything interesting... // - Result alias(const Value *V1, const Value *V2); - - /// canCallModify - We are not interprocedural, so we do nothing exciting. - /// - Result canCallModify(const CallInst &CI, const Value *Ptr) { - return MayAlias; - } - - /// canInvokeModify - We are not interprocedural, so we do nothing exciting. - /// - Result canInvokeModify(const InvokeInst &I, const Value *Ptr) { - return MayAlias; // We are not interprocedural - } + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); +private: + // CheckGEPInstructions - Check two GEP instructions of compatible types and + // equal number of arguments. This checks to see if the index expressions + // preclude the pointers from aliasing... + AliasResult CheckGEPInstructions(GetElementPtrInst *GEP1, unsigned G1Size, + GetElementPtrInst *GEP2, unsigned G2Size); }; #endif From lattner at cs.uiuc.edu Wed Feb 26 13:26:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:26:03 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/AliasAnalysis.h Message-ID: <200302261925.NAA31522@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: AliasAnalysis.h updated: 1.3 -> 1.4 --- Log message: Checkin of new alias analysis interface: * Takes into account the size of the memory reference to determine aliasing. * Expose mod/ref information in a more consistent way --- Diffs of the changes: Index: llvm/include/llvm/Analysis/AliasAnalysis.h diff -u llvm/include/llvm/Analysis/AliasAnalysis.h:1.3 llvm/include/llvm/Analysis/AliasAnalysis.h:1.4 --- llvm/include/llvm/Analysis/AliasAnalysis.h:1.3 Wed Nov 6 11:17:55 2002 +++ llvm/include/llvm/Analysis/AliasAnalysis.h Wed Feb 26 13:24:47 2003 @@ -2,24 +2,61 @@ // // This file defines the generic AliasAnalysis interface, which is used as the // common interface used by all clients of alias analysis information, and -// implemented by all alias analysis implementations. +// implemented by all alias analysis implementations. Mod/Ref information is +// also captured by this interface. // // Implementations of this interface must implement the various virtual methods, // which automatically provides functionality for the entire suite of client // APIs. // +// This API represents memory as a (Pointer, Size) pair. The Pointer component +// specifies the base memory address of the region, the Size specifies how large +// of an area is being queried. If Size is 0, two pointers only alias if they +// are exactly equal. If size is greater than zero, but small, the two pointers +// alias if the areas pointed to overlap. If the size is very large (ie, ~0U), +// then the two pointers alias if they may be pointing to components of the same +// memory object. Pointers that point to two completely different objects in +// memory never alias, regardless of the value of the Size component. +// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H #define LLVM_ANALYSIS_ALIAS_ANALYSIS_H -class Value; -class CallInst; -class InvokeInst; -class BasicBlock; -class Instruction; +#include "llvm/Support/CallSite.h" +class LoadInst; +class StoreInst; +class TargetData; +class AnalysisUsage; +class Pass; + +class AliasAnalysis { + const TargetData *TD; +protected: + /// InitializeAliasAnalysis - Subclasses must call this method to initialize + /// the AliasAnalysis interface before any other methods are called. This is + /// typically called by the run* methods of these subclasses. This may be + /// called multiple times. + /// + void InitializeAliasAnalysis(Pass *P); + + // getAnalysisUsage - All alias analysis implementations should invoke this + // directly (using AliasAnalysis::getAnalysisUsage(AU)) to make sure that + // TargetData is required by the pass. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +public: + AliasAnalysis() : TD(0) {} + virtual ~AliasAnalysis(); // We want to be subclassed + + /// getTargetData - Every alias analysis implementation depends on the size of + /// data items in the current Target. This provides a uniform way to handle + /// it. + const TargetData &getTargetData() const { return *TD; } -struct AliasAnalysis { + //===--------------------------------------------------------------------===// + /// Alias Queries... + /// /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers @@ -27,29 +64,72 @@ /// if (AA.alias(P1, P2)) { ... } /// to check to see if two pointers might alias. /// - enum Result { NoAlias = 0, MayAlias = 1, MustAlias = 2 }; + enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 }; /// alias - The main low level interface to the alias analysis implementation. /// Returns a Result indicating whether the two pointers are aliased to each /// other. This is the interface that must be implemented by specific alias /// analysis implementations. /// - virtual Result alias(const Value *V1, const Value *V2) = 0; - - /// canCallModify - Return a Result that indicates whether the specified - /// function call can modify the memory location pointed to by Ptr. - /// - virtual Result canCallModify(const CallInst &CI, const Value *Ptr) = 0; - - /// canInvokeModify - Return a Result that indicates whether the specified - /// function invoke can modify the memory location pointed to by Ptr. - /// - virtual Result canInvokeModify(const InvokeInst &I, const Value *Ptr) = 0; + virtual AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return MayAlias; + } + + //===--------------------------------------------------------------------===// + /// Simple mod/ref information... + /// + + /// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are + /// bits which may be or'd together. + /// + enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; + + /// getModRefInfo - Return information about whether or not an instruction may + /// read or write memory specified by the pointer operand. An instruction + /// that doesn't read or write memory may be trivially LICM'd for example. + + /// getModRefInfo (for call sites) - Return whether information about whether + /// a particular call site modifies or reads the memory specified by the + /// pointer. + /// + virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size) { + return ModRef; + } + + /// getModRefInfo - Return information about whether two call sites may refer + /// to the same set of memory locations. This function returns NoModRef if + /// the two calls refer to disjoint memory locations, Ref if they both read + /// some of the same memory, Mod if they both write to some of the same + /// memory, and ModRef if they read and write to the same memory. + /// + virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2) { + return ModRef; + } + + /// Convenience functions... + ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); + ModRefResult getModRefInfo(StoreInst*S, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallInst *C, Value *P, unsigned Size) { + return getModRefInfo(CallSite(C), P, Size); + } + ModRefResult getModRefInfo(InvokeInst*I, Value *P, unsigned Size) { + return getModRefInfo(CallSite(I), P, Size); + } + ModRefResult getModRefInfo(Instruction *I, Value *P, unsigned Size) { + switch (I->getOpcode()) { + case Instruction::Load: return getModRefInfo((LoadInst*)I, P, Size); + case Instruction::Store: return getModRefInfo((StoreInst*)I, P, Size); + case Instruction::Call: return getModRefInfo((CallInst*)I, P, Size); + case Instruction::Invoke: return getModRefInfo((InvokeInst*)I, P, Size); + default: return NoModRef; + } + } /// canBasicBlockModify - Return true if it is possible for execution of the /// specified basic block to modify the value pointed to by Ptr. /// - bool canBasicBlockModify(const BasicBlock &BB, const Value *Ptr); + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size); /// canInstructionRangeModify - Return true if it is possible for the /// execution of the specified instructions to modify the value pointed to by @@ -57,9 +137,7 @@ /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. /// bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr); - - virtual ~AliasAnalysis(); // We want to be subclassed + const Value *Ptr, unsigned Size); }; #endif From lattner at cs.uiuc.edu Wed Feb 26 13:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:28:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasAnalysisCounter.cpp Message-ID: <200302261927.NAA31547@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasAnalysisCounter.cpp updated: 1.2 -> 1.3 --- Log message: Adjust to new AA interface Add tracking for Mod/Ref info --- Diffs of the changes: Index: llvm/lib/Analysis/AliasAnalysisCounter.cpp diff -u llvm/lib/Analysis/AliasAnalysisCounter.cpp:1.2 llvm/lib/Analysis/AliasAnalysisCounter.cpp:1.3 --- llvm/lib/Analysis/AliasAnalysisCounter.cpp:1.2 Fri Feb 7 14:39:17 2003 +++ llvm/lib/Analysis/AliasAnalysisCounter.cpp Wed Feb 26 13:27:05 2003 @@ -12,35 +12,59 @@ namespace { class AliasAnalysisCounter : public Pass, public AliasAnalysis { unsigned No, May, Must; + unsigned NoMR, JustRef, JustMod, MR; const char *Name; public: - AliasAnalysisCounter() : No(0), May(0), Must(0) {} + AliasAnalysisCounter() { + No = May = Must = 0; + NoMR = JustRef = JustMod = MR = 0; + } + + void printLine(const char *Desc, unsigned Val, unsigned Sum) { + std::cerr << " " << Val << " " << Desc << " responses (" + << Val*100/Sum << "%)\n"; + } ~AliasAnalysisCounter() { - unsigned Sum = No+May+Must; - if (Sum) { // Print a report if any counted queries occurred... + unsigned AASum = No+May+Must; + unsigned MRSum = NoMR+JustRef+JustMod+MR; + if (AASum + MRSum) { // Print a report if any counted queries occurred... std::cerr << "\n===== Alias Analysis Counter Report =====\n" << " Analysis counted: " << Name << "\n" - << " " << Sum << " Total Alias Queries Performed\n" - << " " << No << " no alias responses (" << No*100/Sum << "%)\n" - << " " << May << " may alias responses (" << May*100/Sum << "%)\n" - << " " << Must << " must alias responses (" <(&getAnalysis())->getPassName(); return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); AU.addRequired(); AU.setPreservesAll(); } - Result count(Result R) { + AliasResult count(AliasResult R) { switch (R) { default: assert(0 && "Unknown alias type!"); case NoAlias: No++; return NoAlias; @@ -48,17 +72,24 @@ case MustAlias: Must++; return MustAlias; } } + ModRefResult count(ModRefResult R) { + switch (R) { + default: assert(0 && "Unknown mod/ref type!"); + case NoModRef: NoMR++; return NoModRef; + case Ref: JustRef++; return Ref; + case Mod: JustMod++; return Mod; + case ModRef: MR++; return ModRef; + } + } // Forwarding functions: just delegate to a real AA implementation, counting // the number of responses... - Result alias(const Value *V1, const Value *V2) { - return count(getAnalysis().alias(V1, V2)); - } - Result canCallModify(const CallInst &CI, const Value *Ptr) { - return count(getAnalysis().canCallModify(CI, Ptr)); + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return count(getAnalysis().alias(V1, V1Size, V2, V2Size)); } - Result canInvokeModify(const InvokeInst &I, const Value *Ptr) { - return count(getAnalysis().canInvokeModify(I, Ptr)); + ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size) { + return count(getAnalysis().getModRefInfo(CS, P, Size)); } }; From lattner at cs.uiuc.edu Wed Feb 26 13:28:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:28:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoadValueNumbering.cpp Message-ID: <200302261927.NAA31558@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoadValueNumbering.cpp updated: 1.1 -> 1.2 --- Log message: Calculate and pass load sizes to the alias analysis infrastructure --- Diffs of the changes: Index: llvm/lib/Analysis/LoadValueNumbering.cpp diff -u llvm/lib/Analysis/LoadValueNumbering.cpp:1.1 llvm/lib/Analysis/LoadValueNumbering.cpp:1.2 --- llvm/lib/Analysis/LoadValueNumbering.cpp:1.1 Fri Aug 30 15:28:10 2002 +++ llvm/lib/Analysis/LoadValueNumbering.cpp Wed Feb 26 13:27:35 2003 @@ -15,6 +15,7 @@ #include "llvm/Analysis/ValueNumbering.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Dominators.h" +#include "llvm/Target/TargetData.h" #include "llvm/Pass.h" #include "llvm/iMemory.h" #include "llvm/BasicBlock.h" @@ -72,6 +73,7 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); + AU.addRequired(); } // getEqualNumberNodes - Return nodes with the same value number as the @@ -81,7 +83,7 @@ std::vector &RetVals) const { if (LoadInst *LI = dyn_cast(V)) { - // If we have a load instruction find all of the load instructions that use + // If we have a load instruction, find all of the load 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 @@ -147,7 +149,8 @@ // (until DestBB) contain an instruction that might invalidate Ptr. // static bool CheckForInvalidatingInst(BasicBlock *BB, BasicBlock *DestBB, - Value *Ptr, AliasAnalysis &AA, + Value *Ptr, unsigned Size, + AliasAnalysis &AA, std::set &VisitedSet) { // Found the termination point! if (BB == DestBB || VisitedSet.count(BB)) return false; @@ -156,12 +159,12 @@ VisitedSet.insert(BB); // Can this basic block modify Ptr? - if (AA.canBasicBlockModify(*BB, 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, AA, VisitedSet)) + if (CheckForInvalidatingInst(*PI, DestBB, Ptr, Size, AA, VisitedSet)) return true; // None of our predecessor blocks contain an invalidating instruction, and we @@ -192,6 +195,12 @@ 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?"); + + // Find out how many bytes of memory are loaded by the load instruction... + unsigned LoadSize = getAnalysis().getTypeSize(L1->getType()); + // L1 now dominates L2. Check to see if the intervening instructions between // the two loads include a store or call... // @@ -199,7 +208,7 @@ // 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)) + if (AA.canInstructionRangeModify(*L1, *L2, LoadAddress, LoadSize)) return false; // Cannot eliminate load // No instructions invalidate the loads, they produce the same value! @@ -208,13 +217,14 @@ // Make sure that there are no store instructions between L1 and the end of // it's basic block... // - if (AA.canInstructionRangeModify(*L1, *BB1->getTerminator(), LoadAddress)) + 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)) + 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, @@ -223,7 +233,8 @@ // std::set VisitedSet; for (pred_iterator PI = pred_begin(BB2), PE = pred_end(BB2); PI != PE; ++PI) - if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, AA, VisitedSet)) + if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, LoadSize, AA, + VisitedSet)) return false; // If we passed all of these checks then we are sure that the two loads From lattner at cs.uiuc.edu Wed Feb 26 13:29:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:29:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasAnalysis.cpp Message-ID: <200302261928.NAA31563@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasAnalysis.cpp updated: 1.10 -> 1.11 --- Log message: - Checkin of the alias analysis work: * Takes into account the size of the memory reference to determine aliasing. * Expose mod/ref information in a more consistent way * BasicAA can now disambiguate A[i][1] and A[j][2] for conservative request sizes --- Diffs of the changes: Index: llvm/lib/Analysis/AliasAnalysis.cpp diff -u llvm/lib/Analysis/AliasAnalysis.cpp:1.10 llvm/lib/Analysis/AliasAnalysis.cpp:1.11 --- llvm/lib/Analysis/AliasAnalysis.cpp:1.10 Sun Feb 9 13:38:11 2003 +++ llvm/lib/Analysis/AliasAnalysis.cpp Wed Feb 26 13:26:51 2003 @@ -19,44 +19,32 @@ #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/BasicBlock.h" -#include "llvm/Support/InstVisitor.h" #include "llvm/iMemory.h" #include "llvm/iOther.h" #include "llvm/Constants.h" +#include "llvm/ConstantHandling.h" #include "llvm/GlobalValue.h" #include "llvm/DerivedTypes.h" +#include "llvm/Target/TargetData.h" // Register the AliasAnalysis interface, providing a nice name to refer to. namespace { RegisterAnalysisGroup Z("Alias Analysis"); } -// CanModify - Define a little visitor class that is used to check to see if -// arbitrary chunks of code can modify a specified pointer. -// -namespace { - struct CanModify : public InstVisitor { - AliasAnalysis &AA; - const Value *Ptr; - - CanModify(AliasAnalysis *aa, const Value *ptr) - : AA(*aa), Ptr(ptr) {} - - bool visitInvokeInst(InvokeInst &II) { - return AA.canInvokeModify(II, Ptr); - } - bool visitCallInst(CallInst &CI) { - return AA.canCallModify(CI, Ptr); - } - bool visitStoreInst(StoreInst &SI) { - return AA.alias(Ptr, SI.getOperand(1)); - } +AliasAnalysis::ModRefResult +AliasAnalysis::getModRefInfo(LoadInst *L, Value *P, unsigned Size) { + return alias(L->getOperand(0), TD->getTypeSize(L->getType()), + P, Size) ? Ref : NoModRef; +} - // Other instructions do not alias anything. - bool visitInstruction(Instruction &I) { return false; } - }; +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; } + // AliasAnalysis destructor: DO NOT move this to the header file for // AliasAnalysis or else clients of the AliasAnalysis class may not depend on // the AliasAnalysis.o file in the current .a file, causing alias analysis @@ -64,19 +52,26 @@ // AliasAnalysis::~AliasAnalysis() {} -/// canBasicBlockModify - Return true if it is possible for execution of the -/// specified basic block to modify the value pointed to by Ptr. +/// setTargetData - Subclasses must call this method to initialize the +/// AliasAnalysis interface before any other methods are called. /// -bool AliasAnalysis::canBasicBlockModify(const BasicBlock &bb, - const Value *Ptr) { - CanModify CM(this, Ptr); - BasicBlock &BB = const_cast(bb); +void AliasAnalysis::InitializeAliasAnalysis(Pass *P) { + TD = &P->getAnalysis(); +} - for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) - if (CM.visit(I)) // Check every instruction in the basic block... - return true; +// getAnalysisUsage - All alias analysis implementations should invoke this +// directly (using AliasAnalysis::getAnalysisUsage(AU)) to make sure that +// TargetData is required by the pass. +void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); // All AA's need TargetData. +} - return false; +/// canBasicBlockModify - Return true if it is possible for execution of the +/// specified basic block to modify the value pointed to by Ptr. +/// +bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB, + const Value *Ptr, unsigned Size) { + return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size); } /// canInstructionRangeModify - Return true if it is possible for the execution @@ -86,18 +81,16 @@ /// bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr) { + const Value *Ptr, unsigned Size) { assert(I1.getParent() == I2.getParent() && "Instructions not in same basic block!"); - CanModify CM(this, Ptr); BasicBlock::iterator I = const_cast(&I1); BasicBlock::iterator E = const_cast(&I2); ++E; // Convert from inclusive to exclusive range. - for (; I != E; ++I) - if (CM.visit(I)) // Check every instruction in the basic block... + for (; I != E; ++I) // Check every instruction in range + if (getModRefInfo(I, const_cast(Ptr), Size) & Mod) return true; - return false; } @@ -120,6 +113,10 @@ RegisterAnalysisGroup Y; } // End of anonymous namespace +void BasicAliasAnalysis::initializePass() { + InitializeAliasAnalysis(this); +} + // hasUniqueAddress - Return true if the @@ -146,8 +143,9 @@ // as array references. Note that this function is heavily tail recursive. // Hopefully we have a smart C++ compiler. :) // -AliasAnalysis::Result BasicAliasAnalysis::alias(const Value *V1, - const Value *V2) { +AliasAnalysis::AliasResult +BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { // Strip off constant pointer refs if they exist if (const ConstantPointerRef *CPR = dyn_cast(V1)) V1 = CPR->getValue(); @@ -163,43 +161,9 @@ // Strip off cast instructions... if (const Instruction *I = dyn_cast(V1)) - return alias(I->getOperand(0), V2); + return alias(I->getOperand(0), V1Size, V2, V2Size); if (const Instruction *I = dyn_cast(V2)) - return alias(V1, I->getOperand(0)); - - // If we have two gep instructions with identical indices, return an alias - // result equal to the alias result of the original pointer... - // - if (const GetElementPtrInst *GEP1 = dyn_cast(V1)) - if (const GetElementPtrInst *GEP2 = dyn_cast(V2)) - if (GEP1->getNumOperands() == GEP2->getNumOperands() && - GEP1->getOperand(0)->getType() == GEP2->getOperand(0)->getType()) { - if (std::equal(GEP1->op_begin()+1, GEP1->op_end(), GEP2->op_begin()+1)) - return alias(GEP1->getOperand(0), GEP2->getOperand(0)); - - // If all of the indexes to the getelementptr are constant, but - // different (well we already know they are different), then we know - // that there cannot be an alias here if the two base pointers DO alias. - // - bool AllConstant = true; - for (unsigned i = 1, e = GEP1->getNumOperands(); i != e; ++i) - if (!isa(GEP1->getOperand(i)) || - !isa(GEP2->getOperand(i))) { - AllConstant = false; - break; - } - - // If we are all constant, then look at where the the base pointers - // alias. If they are known not to alias, then we are dealing with two - // different arrays or something, so no alias is possible. If they are - // known to be the same object, then we cannot alias because we are - // indexing into a different part of the object. As usual, MayAlias - // doesn't tell us anything. - // - if (AllConstant && - alias(GEP1->getOperand(0), GEP2->getOperand(0)) != MayAlias) - return NoAlias; - } + return alias(V1, V1Size, I->getOperand(0), V2Size); // Figure out what objects these things are pointing to if we can... const Value *O1 = getUnderlyingObject(V1); @@ -220,12 +184,28 @@ return NoAlias; // Unique values don't alias null } + // If we have two gep instructions with identical indices, return an alias + // result equal to the alias result of the original pointer... + // + if (const GetElementPtrInst *GEP1 = dyn_cast(V1)) + if (const GetElementPtrInst *GEP2 = dyn_cast(V2)) + if (GEP1->getNumOperands() == GEP2->getNumOperands() && + GEP1->getOperand(0)->getType() == GEP2->getOperand(0)->getType()) { + AliasResult GAlias = + CheckGEPInstructions((GetElementPtrInst*)GEP1, V1Size, + (GetElementPtrInst*)GEP2, V2Size); + if (GAlias != MayAlias) + return GAlias; + } + // Check to see if these two pointers are related by a getelementptr // instruction. If one pointer is a GEP with a non-zero index of the other // pointer, we know they cannot alias. // - if (isa(V2)) + if (isa(V2)) { std::swap(V1, V2); + std::swap(V1Size, V2Size); + } if (const GetElementPtrInst *GEP = dyn_cast(V1)) if (GEP->getOperand(0) == V2) { @@ -239,3 +219,132 @@ return MayAlias; } + +// CheckGEPInstructions - Check two GEP instructions of compatible types and +// equal number of arguments. This checks to see if the index expressions +// preclude the pointers from aliasing... +// +AliasAnalysis::AliasResult +BasicAliasAnalysis::CheckGEPInstructions(GetElementPtrInst *GEP1, unsigned G1S, + GetElementPtrInst *GEP2, unsigned G2S){ + // Do the base pointers alias? + AliasResult BaseAlias = alias(GEP1->getOperand(0), G1S, + GEP2->getOperand(0), G2S); + if (BaseAlias != MustAlias) // No or May alias: We cannot add anything... + return BaseAlias; + + // Find the (possibly empty) initial sequence of equal values... + unsigned NumGEPOperands = GEP1->getNumOperands(); + unsigned UnequalOper = 1; + while (UnequalOper != NumGEPOperands && + GEP1->getOperand(UnequalOper) == GEP2->getOperand(UnequalOper)) + ++UnequalOper; + + // If all operands equal each other, then the derived pointers must + // alias each other... + if (UnequalOper == NumGEPOperands) return MustAlias; + + // So now we know that the indexes derived from the base pointers, + // which are known to alias, are different. We can still determine a + // no-alias result if there are differing constant pairs in the index + // chain. For example: + // A[i][0] != A[j][1] iff (&A[0][1]-&A[0][0] >= std::max(G1S, G2S)) + // + unsigned SizeMax = std::max(G1S, G2S); + if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work... + + // Scan for the first operand that is constant and unequal in the + // two getelemenptrs... + unsigned FirstConstantOper = UnequalOper; + for (; FirstConstantOper != NumGEPOperands; ++FirstConstantOper) { + const Value *G1Oper = GEP1->getOperand(FirstConstantOper); + const Value *G2Oper = GEP2->getOperand(FirstConstantOper); + if (G1Oper != G2Oper && // Found non-equal constant indexes... + isa(G1Oper) && isa(G2Oper)) { + // Make sure they are comparable... and make sure the GEP with + // the smaller leading constant is GEP1. + ConstantBool *Compare = + *cast(GEP1->getOperand(FirstConstantOper)) > + *cast(GEP2->getOperand(FirstConstantOper)); + if (Compare) { // If they are comparable... + if (Compare->getValue()) + std::swap(GEP1, GEP2); // Make GEP1 < GEP2 + break; + } + } + } + + // No constant operands, we cannot tell anything... + if (FirstConstantOper == NumGEPOperands) return MayAlias; + + // If there are non-equal constants arguments, then we can figure + // out a minimum known delta between the two index expressions... at + // this point we know that the first constant index of GEP1 is less + // than the first constant index of GEP2. + // + std::vector Indices1; + Indices1.reserve(NumGEPOperands-1); + for (unsigned i = 1; i != FirstConstantOper; ++i) + Indices1.push_back(Constant::getNullValue(GEP1->getOperand(i) + ->getType())); + std::vector Indices2; + Indices2.reserve(NumGEPOperands-1); + Indices2 = Indices1; // Copy the zeros prefix... + + // Add the two known constant operands... + Indices1.push_back((Value*)GEP1->getOperand(FirstConstantOper)); + Indices2.push_back((Value*)GEP2->getOperand(FirstConstantOper)); + + const Type *GEPPointerTy = GEP1->getOperand(0)->getType(); + + // Loop over the rest of the operands... + for (unsigned i = FirstConstantOper+1; i!=NumGEPOperands; ++i){ + const Value *Op1 = GEP1->getOperand(i); + const Value *Op2 = GEP1->getOperand(i); + if (Op1 == Op2) { // If they are equal, use a zero index... + Indices1.push_back(Constant::getNullValue(Op1->getType())); + Indices2.push_back(Indices1.back()); + } else { + if (isa(Op1)) + Indices1.push_back((Value*)Op1); + else { + // GEP1 is known to produce a value less than GEP2. To be + // conservatively correct, we must assume the largest + // possible constant is used in this position. This cannot + // be the initial index to the GEP instructions (because we + // know we have at least one element before this one with + // the different constant arguments), so we know that the + // current index must be into either a struct or array. + // Because of this, we can calculate the maximum value + // possible. + // + const Type *ElTy = GEP1->getIndexedType(GEPPointerTy, + Indices1, true); + if (const StructType *STy = dyn_cast(ElTy)) { + Indices1.push_back(ConstantUInt::get(Type::UByteTy, + STy->getNumContainedTypes())); + } else { + Indices1.push_back(ConstantSInt::get(Type::LongTy, + cast(ElTy)->getNumElements())); + } + } + + if (isa(Op2)) + Indices2.push_back((Value*)Op2); + else // Conservatively assume the minimum value for this index + Indices2.push_back(Constant::getNullValue(Op1->getType())); + } + } + + unsigned Offset1 = getTargetData().getIndexedOffset(GEPPointerTy, Indices1); + unsigned Offset2 = getTargetData().getIndexedOffset(GEPPointerTy, Indices2); + assert(Offset1 < Offset2 &&"There is at least one different constant here!"); + + if (Offset2-Offset1 >= SizeMax) { + //std::cerr << "Determined that these two GEP's don't alias [" + // << SizeMax << " bytes]: \n" << *GEP1 << *GEP2; + return NoAlias; + } + return MayAlias; +} + From lattner at cs.uiuc.edu Wed Feb 26 13:30:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:30:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp Message-ID: <200302261929.NAA31579@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.21 -> 1.22 --- Log message: Convert to work with new AliasAnalysis interface by conservatively assuming all pointers are arbitrarily large accesses --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.21 llvm/lib/Transforms/Scalar/LICM.cpp:1.22 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.21 Sun Feb 23 21:52:32 2003 +++ llvm/lib/Transforms/Scalar/LICM.cpp Wed Feb 26 13:28:55 2003 @@ -123,17 +123,17 @@ LoopBodyInfo::PointerClass LoopBodyInfo::calculatePointerInfo(Value *V, AliasAnalysis &AA) const { for (unsigned i = 0, e = Calls.size(); i != e; ++i) - if (AA.canCallModify(*Calls[i], V)) + if (AA.getModRefInfo(Calls[i], V, ~0)) return PointerMayStore; for (unsigned i = 0, e = Invokes.size(); i != e; ++i) - if (AA.canInvokeModify(*Invokes[i], V)) + if (AA.getModRefInfo(Invokes[i], V, ~0)) return PointerMayStore; PointerClass Result = PointerNoStore; for (std::set::const_iterator I = StoredPointers.begin(), E = StoredPointers.end(); I != E; ++I) - if (AA.alias(V, *I)) + if (AA.alias(V, ~0, *I, ~0)) if (V == *I) Result = PointerMustStore; // If this is the only alias, return must else @@ -485,7 +485,7 @@ bool PointerOk = true; for (std::set::const_iterator I =CurLBI->LoadedPointers.begin(), E = CurLBI->LoadedPointers.end(); I != E; ++I) - if (AA->alias(V, *I) == AliasAnalysis::MayAlias) { + if (AA->alias(V, ~0, *I, ~0) == AliasAnalysis::MayAlias) { PointerOk = false; break; } @@ -503,13 +503,13 @@ for (std::set::const_iterator I = CurLBI->LoadedPointers.begin(), E = CurLBI->LoadedPointers.end(); I != E; ++I) - if (AA->alias(V, *I) == AliasAnalysis::MustAlias) + if (AA->alias(V, ~0, *I, ~0) == AliasAnalysis::MustAlias) ValueToAllocaMap[*I] = AI; for (std::set::const_iterator I = CurLBI->StoredPointers.begin(), E = CurLBI->StoredPointers.end(); I != E; ++I) - if (AA->alias(V, *I) == AliasAnalysis::MustAlias) + if (AA->alias(V, ~0, *I, ~0) == AliasAnalysis::MustAlias) ValueToAllocaMap[*I] = AI; } } From lattner at cs.uiuc.edu Wed Feb 26 13:30:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:30:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasSetTracker.cpp Message-ID: <200302261929.NAA31586@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasSetTracker.cpp updated: 1.2 -> 1.3 --- Log message: Convert to work with new AliasAnalysis interface by conservatively assuming all pointers are arbitrarily large accesses --- Diffs of the changes: Index: llvm/lib/Analysis/AliasSetTracker.cpp diff -u llvm/lib/Analysis/AliasSetTracker.cpp:1.2 llvm/lib/Analysis/AliasSetTracker.cpp:1.3 --- llvm/lib/Analysis/AliasSetTracker.cpp:1.2 Mon Feb 24 14:37:56 2003 +++ llvm/lib/Analysis/AliasSetTracker.cpp Wed Feb 26 13:28:57 2003 @@ -13,6 +13,8 @@ #include "llvm/Assembly/Writer.h" #include "llvm/Support/InstIterator.h" +// FIXME: This should keep sizes associated with pointers! + /// mergeSetIn - Merge the specified alias set into this alias set... /// void AliasSet::mergeSetIn(AliasSet &AS) { @@ -59,7 +61,7 @@ if (isMustAlias()) // Check to see if we have to downgrade to _may_ alias if (Value *V = getSomePointer()) - if (AA.alias(V, Entry.first) == AliasAnalysis::MayAlias) + if (AA.alias(V, ~0, Entry.first, ~0) == AliasAnalysis::MayAlias) AliasTy = MayAlias; Entry.second.setAliasSet(this); @@ -89,13 +91,13 @@ // SOME value in the set... Value *SomePtr = getSomePointer(); assert(SomePtr && "Empty must-alias set??"); - return AA.alias(SomePtr, Ptr); + return AA.alias(SomePtr, ~0, Ptr, ~0); } // If this is a may-alias set, we have to check all of the pointers in the set // to be sure it doesn't alias the set... for (iterator I = begin(), E = end(); I != E; ++I) - if (AA.alias(Ptr, *I)) + if (AA.alias(Ptr, ~0, *I, ~0)) return true; // Check the call sites list and invoke list... @@ -119,7 +121,7 @@ AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr) { AliasSet *FoundSet = 0; for (iterator I = begin(), E = end(); I != E; ++I) - if (I->aliasesPointer(Ptr, AA)) { + if (!I->Forward && I->aliasesPointer(Ptr, AA)) { if (FoundSet == 0) { // If this is the first alias set ptr can go into... FoundSet = I; // Remember it. } else { // Otherwise, we must merge the sets... @@ -133,10 +135,10 @@ AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { AliasSet *FoundSet = 0; for (iterator I = begin(), E = end(); I != E; ++I) - if (I->aliasesCallSite(CS, AA)) { + if (!I->Forward && I->aliasesCallSite(CS, AA)) { if (FoundSet == 0) { // If this is the first alias set ptr can go into... FoundSet = I; // Remember it. - } else { // Otherwise, we must merge the sets... + } else if (!I->Forward) { // Otherwise, we must merge the sets... FoundSet->mergeSetIn(*I); // Merge in contents... } } From lattner at cs.uiuc.edu Wed Feb 26 13:30:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:30:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasAnalysisEvaluator.cpp Message-ID: <200302261929.NAA31597@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasAnalysisEvaluator.cpp updated: 1.5 -> 1.6 --- Log message: Adjust to new AA interface --- Diffs of the changes: Index: llvm/lib/Analysis/AliasAnalysisEvaluator.cpp diff -u llvm/lib/Analysis/AliasAnalysisEvaluator.cpp:1.5 llvm/lib/Analysis/AliasAnalysisEvaluator.cpp:1.6 --- llvm/lib/Analysis/AliasAnalysisEvaluator.cpp:1.5 Tue Feb 11 17:12:09 2003 +++ llvm/lib/Analysis/AliasAnalysisEvaluator.cpp Wed Feb 26 13:29:16 2003 @@ -69,7 +69,7 @@ for (std::vector::iterator I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) for (std::vector::iterator I2 = Pointers.begin(); I2 != I1; ++I2) - switch (AA.alias(*I1, *I2)) { + switch (AA.alias(*I1, 0, *I2, 0)) { case AliasAnalysis::NoAlias: PrintResults("No", PrintNo, *I1, *I2); ++No; break; From lattner at cs.uiuc.edu Wed Feb 26 13:30:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:30:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/DataStructureAA.cpp Steensgaard.cpp Message-ID: <200302261929.NAA31610@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: DataStructureAA.cpp updated: 1.2 -> 1.3 Steensgaard.cpp updated: 1.27 -> 1.28 --- Log message: Adjust to implement new AA interface --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/DataStructureAA.cpp diff -u llvm/lib/Analysis/DataStructure/DataStructureAA.cpp:1.2 llvm/lib/Analysis/DataStructure/DataStructureAA.cpp:1.3 --- llvm/lib/Analysis/DataStructure/DataStructureAA.cpp:1.2 Fri Feb 7 14:39:48 2003 +++ llvm/lib/Analysis/DataStructure/DataStructureAA.cpp Wed Feb 26 13:29:36 2003 @@ -24,11 +24,13 @@ // program. // bool run(Module &M) { + InitializeAliasAnalysis(this); TD = &getAnalysis(); return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); AU.setPreservesAll(); // Does not transform code... AU.addRequired(); // Uses TD Datastructures AU.addRequired(); // Chains to another AA impl... @@ -39,19 +41,8 @@ // // alias - This is the only method here that does anything interesting... - Result alias(const Value *V1, const Value *V2); - - /// canCallModify - Not implemented yet: FIXME - /// - Result canCallModify(const CallInst &CI, const Value *Ptr) { - return MayAlias; - } - - /// canInvokeModify - Not implemented yet: FIXME - /// - Result canInvokeModify(const InvokeInst &I, const Value *Ptr) { - return MayAlias; - } + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); }; // Register the pass... @@ -75,7 +66,9 @@ } // alias - This is the only method here that does anything interesting... -AliasAnalysis::Result DSAA::alias(const Value *V1, const Value *V2) { +AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + // FIXME: This should handle the Size argument as well! const Function *F1 = getValueFunction(V1); const Function *F2 = getValueFunction(V2); assert((!F1 || !F2 || F1 == F2) && "Alias query for 2 different functions?"); @@ -113,5 +106,5 @@ // FIXME: we could improve on this by checking the globals graph for aliased // global queries... - return getAnalysis().alias(V1, V2); + return getAnalysis().alias(V1, V1Size, V2, V2Size); } Index: llvm/lib/Analysis/DataStructure/Steensgaard.cpp diff -u llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.27 llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.28 --- llvm/lib/Analysis/DataStructure/Steensgaard.cpp:1.27 Thu Feb 13 15:44:18 2003 +++ llvm/lib/Analysis/DataStructure/Steensgaard.cpp Wed Feb 26 13:29:36 2003 @@ -18,7 +18,7 @@ DSGraph *ResultGraph; DSGraph *GlobalsGraph; // FIXME: Eliminate globals graph stuff from DNE public: - Steens() : ResultGraph(0) {} + Steens() : ResultGraph(0), GlobalsGraph(0) {} ~Steens() { releaseMyMemory(); assert(ResultGraph == 0 && "releaseMemory not called?"); @@ -36,6 +36,7 @@ virtual void releaseMyMemory() { delete ResultGraph; ResultGraph = 0; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); AU.setPreservesAll(); // Does not transform code... AU.addRequired(); // Uses local dsgraph AU.addRequired(); // Chains to another AA impl... @@ -52,20 +53,9 @@ // // alias - This is the only method here that does anything interesting... - Result alias(const Value *V1, const Value *V2); + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); - /// canCallModify - Not implemented yet: FIXME - /// - Result canCallModify(const CallInst &CI, const Value *Ptr) { - return MayAlias; - } - - /// canInvokeModify - Not implemented yet: FIXME - /// - Result canInvokeModify(const InvokeInst &I, const Value *Ptr) { - return MayAlias; - } - private: void ResolveFunctionCall(Function *F, const DSCallSite &Call, DSNodeHandle &RetVal); @@ -108,6 +98,7 @@ /// program. /// bool Steens::run(Module &M) { + InitializeAliasAnalysis(this); assert(ResultGraph == 0 && "Result graph already allocated!"); LocalDataStructures &LDS = getAnalysis(); @@ -212,7 +203,9 @@ } // alias - This is the only method here that does anything interesting... -AliasAnalysis::Result Steens::alias(const Value *V1, const Value *V2) { +AliasAnalysis::AliasResult Steens::alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + // FIXME: HANDLE Size argument! assert(ResultGraph && "Result graph has not been computed yet!"); hash_map &GSM = ResultGraph->getScalarMap(); @@ -239,5 +232,5 @@ // If we cannot determine alias properties based on our graph, fall back on // some other AA implementation. // - return getAnalysis().alias(V1, V2); + return getAnalysis().alias(V1, V1Size, V2, V2Size); } From lattner at cs.uiuc.edu Wed Feb 26 13:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:42:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/BasicAliasAnalysis.h Message-ID: <200302261941.NAA32556@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: BasicAliasAnalysis.h (r1.7) removed --- Log message: BasicAA doesn't need a public header --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Feb 26 13:43:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:43:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp AliasAnalysis.cpp Message-ID: <200302261942.NAA32563@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp added (r1.1) AliasAnalysis.cpp updated: 1.11 -> 1.12 --- Log message: Move BasicAA pass out to it's own header file --- Diffs of the changes: Index: llvm/lib/Analysis/AliasAnalysis.cpp diff -u llvm/lib/Analysis/AliasAnalysis.cpp:1.11 llvm/lib/Analysis/AliasAnalysis.cpp:1.12 --- llvm/lib/Analysis/AliasAnalysis.cpp:1.11 Wed Feb 26 13:26:51 2003 +++ llvm/lib/Analysis/AliasAnalysis.cpp Wed Feb 26 13:41:54 2003 @@ -17,14 +17,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/BasicAliasAnalysis.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/BasicBlock.h" #include "llvm/iMemory.h" -#include "llvm/iOther.h" -#include "llvm/Constants.h" -#include "llvm/ConstantHandling.h" -#include "llvm/GlobalValue.h" -#include "llvm/DerivedTypes.h" #include "llvm/Target/TargetData.h" // Register the AliasAnalysis interface, providing a nice name to refer to. @@ -94,257 +89,11 @@ return false; } -//===----------------------------------------------------------------------===// -// BasicAliasAnalysis Pass Implementation -//===----------------------------------------------------------------------===// +// Because of the way .a files work, we must force the BasicAA implementation to +// be pulled in if the AliasAnalysis classes are pulled in. Otherwise we run +// the risk of AliasAnalysis being used, but the default implementation not +// being linked into the tool that uses it. // -// Because of the way .a files work, the implementation of the -// BasicAliasAnalysis class MUST be in the AliasAnalysis file itself, or else we -// run the risk of AliasAnalysis being used, but the default implementation not -// being linked into the tool that uses it. As such, we register and implement -// the class here. -// -namespace { - // Register this pass... - RegisterOpt - X("basicaa", "Basic Alias Analysis (default AA impl)"); - - // Declare that we implement the AliasAnalysis interface - RegisterAnalysisGroup Y; -} // End of anonymous namespace - -void BasicAliasAnalysis::initializePass() { - InitializeAliasAnalysis(this); -} - - - -// hasUniqueAddress - Return true if the -static inline bool hasUniqueAddress(const Value *V) { - return isa(V) || isa(V) || isa(V); -} - -static const Value *getUnderlyingObject(const Value *V) { - if (!isa(V->getType())) return 0; - - // If we are at some type of object... return it. - if (hasUniqueAddress(V)) return V; - - // Traverse through different addressing mechanisms... - if (const Instruction *I = dyn_cast(V)) { - if (isa(I) || isa(I)) - return getUnderlyingObject(I->getOperand(0)); - } - return 0; -} - - -// 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. -// Hopefully we have a smart C++ compiler. :) -// -AliasAnalysis::AliasResult -BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size) { - // Strip off constant pointer refs if they exist - if (const ConstantPointerRef *CPR = dyn_cast(V1)) - V1 = CPR->getValue(); - if (const ConstantPointerRef *CPR = dyn_cast(V2)) - V2 = CPR->getValue(); - - // Are we checking for alias of the same value? - if (V1 == V2) return MustAlias; - - if ((!isa(V1->getType()) || !isa(V2->getType())) && - V1->getType() != Type::LongTy && V2->getType() != Type::LongTy) - return NoAlias; // Scalars cannot alias each other - - // Strip off cast instructions... - if (const Instruction *I = dyn_cast(V1)) - return alias(I->getOperand(0), V1Size, V2, V2Size); - if (const Instruction *I = dyn_cast(V2)) - return alias(V1, V1Size, I->getOperand(0), V2Size); - - // Figure out what objects these things are pointing to if we can... - const Value *O1 = getUnderlyingObject(V1); - const Value *O2 = getUnderlyingObject(V2); - - // Pointing at a discernable object? - if (O1 && O2) { - // If they are two different objects, we know that we have no alias... - if (O1 != O2) return NoAlias; - - // If they are the same object, they we can look at the indexes. If they - // index off of the object is the same for both pointers, they must alias. - // If they are provably different, they must not alias. Otherwise, we can't - // tell anything. - } else if (O1 && isa(V2)) { - return NoAlias; // Unique values don't alias null - } else if (O2 && isa(V1)) { - return NoAlias; // Unique values don't alias null - } - - // If we have two gep instructions with identical indices, return an alias - // result equal to the alias result of the original pointer... - // - if (const GetElementPtrInst *GEP1 = dyn_cast(V1)) - if (const GetElementPtrInst *GEP2 = dyn_cast(V2)) - if (GEP1->getNumOperands() == GEP2->getNumOperands() && - GEP1->getOperand(0)->getType() == GEP2->getOperand(0)->getType()) { - AliasResult GAlias = - CheckGEPInstructions((GetElementPtrInst*)GEP1, V1Size, - (GetElementPtrInst*)GEP2, V2Size); - if (GAlias != MayAlias) - return GAlias; - } - - // Check to see if these two pointers are related by a getelementptr - // instruction. If one pointer is a GEP with a non-zero index of the other - // pointer, we know they cannot alias. - // - if (isa(V2)) { - std::swap(V1, V2); - std::swap(V1Size, V2Size); - } - - if (const GetElementPtrInst *GEP = dyn_cast(V1)) - if (GEP->getOperand(0) == V2) { - // If there is at least one non-zero constant index, we know they cannot - // alias. - for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i) - if (const Constant *C = dyn_cast(GEP->getOperand(i))) - if (!C->isNullValue()) - return NoAlias; - } - - return MayAlias; -} - -// CheckGEPInstructions - Check two GEP instructions of compatible types and -// equal number of arguments. This checks to see if the index expressions -// preclude the pointers from aliasing... -// -AliasAnalysis::AliasResult -BasicAliasAnalysis::CheckGEPInstructions(GetElementPtrInst *GEP1, unsigned G1S, - GetElementPtrInst *GEP2, unsigned G2S){ - // Do the base pointers alias? - AliasResult BaseAlias = alias(GEP1->getOperand(0), G1S, - GEP2->getOperand(0), G2S); - if (BaseAlias != MustAlias) // No or May alias: We cannot add anything... - return BaseAlias; - - // Find the (possibly empty) initial sequence of equal values... - unsigned NumGEPOperands = GEP1->getNumOperands(); - unsigned UnequalOper = 1; - while (UnequalOper != NumGEPOperands && - GEP1->getOperand(UnequalOper) == GEP2->getOperand(UnequalOper)) - ++UnequalOper; - - // If all operands equal each other, then the derived pointers must - // alias each other... - if (UnequalOper == NumGEPOperands) return MustAlias; - - // So now we know that the indexes derived from the base pointers, - // which are known to alias, are different. We can still determine a - // no-alias result if there are differing constant pairs in the index - // chain. For example: - // A[i][0] != A[j][1] iff (&A[0][1]-&A[0][0] >= std::max(G1S, G2S)) - // - unsigned SizeMax = std::max(G1S, G2S); - if (SizeMax == ~0U) return MayAlias; // Avoid frivolous work... - - // Scan for the first operand that is constant and unequal in the - // two getelemenptrs... - unsigned FirstConstantOper = UnequalOper; - for (; FirstConstantOper != NumGEPOperands; ++FirstConstantOper) { - const Value *G1Oper = GEP1->getOperand(FirstConstantOper); - const Value *G2Oper = GEP2->getOperand(FirstConstantOper); - if (G1Oper != G2Oper && // Found non-equal constant indexes... - isa(G1Oper) && isa(G2Oper)) { - // Make sure they are comparable... and make sure the GEP with - // the smaller leading constant is GEP1. - ConstantBool *Compare = - *cast(GEP1->getOperand(FirstConstantOper)) > - *cast(GEP2->getOperand(FirstConstantOper)); - if (Compare) { // If they are comparable... - if (Compare->getValue()) - std::swap(GEP1, GEP2); // Make GEP1 < GEP2 - break; - } - } - } - - // No constant operands, we cannot tell anything... - if (FirstConstantOper == NumGEPOperands) return MayAlias; - - // If there are non-equal constants arguments, then we can figure - // out a minimum known delta between the two index expressions... at - // this point we know that the first constant index of GEP1 is less - // than the first constant index of GEP2. - // - std::vector Indices1; - Indices1.reserve(NumGEPOperands-1); - for (unsigned i = 1; i != FirstConstantOper; ++i) - Indices1.push_back(Constant::getNullValue(GEP1->getOperand(i) - ->getType())); - std::vector Indices2; - Indices2.reserve(NumGEPOperands-1); - Indices2 = Indices1; // Copy the zeros prefix... - - // Add the two known constant operands... - Indices1.push_back((Value*)GEP1->getOperand(FirstConstantOper)); - Indices2.push_back((Value*)GEP2->getOperand(FirstConstantOper)); - - const Type *GEPPointerTy = GEP1->getOperand(0)->getType(); - - // Loop over the rest of the operands... - for (unsigned i = FirstConstantOper+1; i!=NumGEPOperands; ++i){ - const Value *Op1 = GEP1->getOperand(i); - const Value *Op2 = GEP1->getOperand(i); - if (Op1 == Op2) { // If they are equal, use a zero index... - Indices1.push_back(Constant::getNullValue(Op1->getType())); - Indices2.push_back(Indices1.back()); - } else { - if (isa(Op1)) - Indices1.push_back((Value*)Op1); - else { - // GEP1 is known to produce a value less than GEP2. To be - // conservatively correct, we must assume the largest - // possible constant is used in this position. This cannot - // be the initial index to the GEP instructions (because we - // know we have at least one element before this one with - // the different constant arguments), so we know that the - // current index must be into either a struct or array. - // Because of this, we can calculate the maximum value - // possible. - // - const Type *ElTy = GEP1->getIndexedType(GEPPointerTy, - Indices1, true); - if (const StructType *STy = dyn_cast(ElTy)) { - Indices1.push_back(ConstantUInt::get(Type::UByteTy, - STy->getNumContainedTypes())); - } else { - Indices1.push_back(ConstantSInt::get(Type::LongTy, - cast(ElTy)->getNumElements())); - } - } - - if (isa(Op2)) - Indices2.push_back((Value*)Op2); - else // Conservatively assume the minimum value for this index - Indices2.push_back(Constant::getNullValue(Op1->getType())); - } - } - - unsigned Offset1 = getTargetData().getIndexedOffset(GEPPointerTy, Indices1); - unsigned Offset2 = getTargetData().getIndexedOffset(GEPPointerTy, Indices2); - assert(Offset1 < Offset2 &&"There is at least one different constant here!"); - - if (Offset2-Offset1 >= SizeMax) { - //std::cerr << "Determined that these two GEP's don't alias [" - // << SizeMax << " bytes]: \n" << *GEP1 << *GEP2; - return NoAlias; - } - return MayAlias; -} +extern void BasicAAStub(); +static IncludeFile INCLUDE_BASICAA_CPP((void*)&BasicAAStub); From lattner at cs.uiuc.edu Wed Feb 26 13:57:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:57:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx 2002-12-23-SubProblem.llx Makefile Message-ID: <200302261956.NAA00637@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2002-12-23-LocalRAProblem.llx updated: 1.1 -> 1.2 2002-12-23-SubProblem.llx updated: 1.1 -> 1.2 Makefile updated: 1.5 -> 1.6 --- Log message: Rename -no-* to -disable-* --- Diffs of the changes: Index: llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx diff -u llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx:1.1 llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx:1.2 --- llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx:1.1 Mon Dec 23 17:51:30 2002 +++ llvm/test/Regression/Jello/2002-12-23-LocalRAProblem.llx Wed Feb 26 13:56:27 2003 @@ -1,4 +1,4 @@ -; RUN: as < %s | lli -force-interpreter=false -no-local-ra=false +; RUN: as < %s | lli -force-interpreter=false -disable-local-ra=false ;-print-machineinstrs int %main() { Index: llvm/test/Regression/Jello/2002-12-23-SubProblem.llx diff -u llvm/test/Regression/Jello/2002-12-23-SubProblem.llx:1.1 llvm/test/Regression/Jello/2002-12-23-SubProblem.llx:1.2 --- llvm/test/Regression/Jello/2002-12-23-SubProblem.llx:1.1 Mon Dec 23 17:51:30 2002 +++ llvm/test/Regression/Jello/2002-12-23-SubProblem.llx Wed Feb 26 13:56:27 2003 @@ -1,4 +1,4 @@ -; RUN: as < %s | lli -force-interpreter=false -no-local-ra +; RUN: as < %s | lli -force-interpreter=false -disable-local-ra int %main(int %B) { ;%B = add int 0, 1 Index: llvm/test/Regression/Jello/Makefile diff -u llvm/test/Regression/Jello/Makefile:1.5 llvm/test/Regression/Jello/Makefile:1.6 --- llvm/test/Regression/Jello/Makefile:1.5 Sat Dec 28 14:01:23 2002 +++ llvm/test/Regression/Jello/Makefile Wed Feb 26 13:56:27 2003 @@ -13,7 +13,7 @@ LLI_FLAGS = -force-interpreter=false ifdef DISABLE_FP_ELIM -LLI_FLAGS += -no-fp-elim +LLI_FLAGS += -disable-fp-elim endif Output/%.out: Output/%.bc $(LLI) From lattner at cs.uiuc.edu Wed Feb 26 13:58:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:58:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasAnalysis.cpp Message-ID: <200302261957.NAA00656@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasAnalysis.cpp updated: 1.12 -> 1.13 --- Log message: Add new -no-aa implementation --- Diffs of the changes: Index: llvm/lib/Analysis/AliasAnalysis.cpp diff -u llvm/lib/Analysis/AliasAnalysis.cpp:1.12 llvm/lib/Analysis/AliasAnalysis.cpp:1.13 --- llvm/lib/Analysis/AliasAnalysis.cpp:1.12 Wed Feb 26 13:41:54 2003 +++ llvm/lib/Analysis/AliasAnalysis.cpp Wed Feb 26 13:57:10 2003 @@ -97,3 +97,22 @@ extern void BasicAAStub(); static IncludeFile INCLUDE_BASICAA_CPP((void*)&BasicAAStub); + +namespace { + struct NoAA : public ImmutablePass, public AliasAnalysis { + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AliasAnalysis::getAnalysisUsage(AU); + } + + virtual void initializePass() { + InitializeAliasAnalysis(this); + } + }; + + // Register this pass... + RegisterOpt + X("no-aa", "No Alias Analysis (always returns 'may' alias)"); + + // Declare that we implement the AliasAnalysis interface + RegisterAnalysisGroup Y; +} // End of anonymous namespace From lattner at cs.uiuc.edu Wed Feb 26 13:59:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 13:59:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp X86TargetMachine.cpp Message-ID: <200302261958.NAA00674@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.30 -> 1.31 X86TargetMachine.cpp updated: 1.13 -> 1.14 --- Log message: Rename -no-* to -disable-* --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.30 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.31 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.30 Wed Jan 15 20:20:12 2003 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Wed Feb 26 13:58:15 2003 @@ -19,7 +19,7 @@ namespace { cl::opt - NoFPElim("no-fp-elim", + NoFPElim("disable-fp-elim", cl::desc("Disable frame pointer elimination optimization")); } Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.13 llvm/lib/Target/X86/X86TargetMachine.cpp:1.14 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.13 Wed Jan 15 20:20:12 2003 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Wed Feb 26 13:58:15 2003 @@ -15,7 +15,7 @@ #include namespace { - cl::opt NoLocalRA("no-local-ra", + cl::opt NoLocalRA("disable-local-ra", cl::desc("Use Simple RA instead of Local RegAlloc")); cl::opt PrintCode("print-machineinstrs", cl::desc("Print generated machine code")); From lattner at cs.uiuc.edu Wed Feb 26 14:01:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 14:01:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/TEST.aa.Makefile Message-ID: <200302262000.OAA00708@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: TEST.aa.Makefile updated: 1.2 -> 1.3 --- Log message: Rename -no-* to -disable-* --- Diffs of the changes: Index: llvm/test/Programs/TEST.aa.Makefile diff -u llvm/test/Programs/TEST.aa.Makefile:1.2 llvm/test/Programs/TEST.aa.Makefile:1.3 --- llvm/test/Programs/TEST.aa.Makefile:1.2 Fri Feb 14 17:26:35 2003 +++ llvm/test/Programs/TEST.aa.Makefile Wed Feb 26 14:00:09 2003 @@ -16,7 +16,7 @@ AA_IMPLS := basic steens-fi andersens steens ds-fi ds -SUFFIX = -aa-eval -time-passes -no-output -no-verify < $< 2> $@ +SUFFIX = -aa-eval -time-passes -disable-output -disable-verify < $< 2> $@ $(PROGRAMS_TO_TEST:%=Output/%.aa.basic.txt): \ Output/%.aa.basic.txt: Output/%.lib.bc $(LOPT) From lattner at cs.uiuc.edu Wed Feb 26 14:01:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 14:01:03 2003 Subject: [llvm-commits] CVS: llvm/tools/opt/opt.cpp Message-ID: <200302262000.OAA00733@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: opt.cpp updated: 1.76 -> 1.77 --- Log message: Rename -no-* to -disable-* --- Diffs of the changes: Index: llvm/tools/opt/opt.cpp diff -u llvm/tools/opt/opt.cpp:1.76 llvm/tools/opt/opt.cpp:1.77 --- llvm/tools/opt/opt.cpp:1.76 Wed Feb 12 12:45:08 2003 +++ llvm/tools/opt/opt.cpp Wed Feb 26 14:00:41 2003 @@ -48,10 +48,11 @@ PrintEachXForm("p", cl::desc("Print module after each transformation")); static cl::opt -NoOutput("no-output", cl::desc("Do not write result bytecode file"), cl::Hidden); +NoOutput("disable-output", + cl::desc("Do not write result bytecode file"), cl::Hidden); static cl::opt -NoVerify("no-verify", cl::desc("Do not verify result module"), cl::Hidden); +NoVerify("disable-verify", cl::desc("Do not verify result module"), cl::Hidden); static cl::opt Quiet("q", cl::desc("Don't print 'program modified' message")); From lattner at cs.uiuc.edu Wed Feb 26 15:29:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 15:29:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200302262128.PAA02283@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp updated: 1.1 -> 1.2 --- Log message: Fix several bugs in basic-aa --- Diffs of the changes: Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.1 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.2 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.1 Wed Feb 26 13:41:54 2003 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Wed Feb 26 15:28:49 2003 @@ -142,8 +142,10 @@ std::swap(V1Size, V2Size); } - if (const GetElementPtrInst *GEP = dyn_cast(V1)) - if (GEP->getOperand(0) == V2) { + if (const GetElementPtrInst *GEP = dyn_cast(V1)) { + AliasResult R = alias(GEP->getOperand(0), V1Size, V2, V2Size); + if (R == NoAlias) return NoAlias; + if (R == MustAlias) { // If there is at least one non-zero constant index, we know they cannot // alias. for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i) @@ -151,6 +153,7 @@ if (!C->isNullValue()) return NoAlias; } + } return MayAlias; } @@ -220,8 +223,10 @@ std::vector Indices1; Indices1.reserve(NumGEPOperands-1); for (unsigned i = 1; i != FirstConstantOper; ++i) - Indices1.push_back(Constant::getNullValue(GEP1->getOperand(i) - ->getType())); + if (GEP1->getOperand(i)->getType() == Type::UByteTy) + Indices1.push_back(GEP1->getOperand(i)); + else + Indices1.push_back(Constant::getNullValue(Type::LongTy)); std::vector Indices2; Indices2.reserve(NumGEPOperands-1); Indices2 = Indices1; // Copy the zeros prefix... @@ -235,7 +240,7 @@ // Loop over the rest of the operands... for (unsigned i = FirstConstantOper+1; i!=NumGEPOperands; ++i){ const Value *Op1 = GEP1->getOperand(i); - const Value *Op2 = GEP1->getOperand(i); + const Value *Op2 = GEP2->getOperand(i); if (Op1 == Op2) { // If they are equal, use a zero index... Indices1.push_back(Constant::getNullValue(Op1->getType())); Indices2.push_back(Indices1.back()); From lattner at cs.uiuc.edu Wed Feb 26 15:41:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 15:41:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/2003-02-26-AccessSizeTest.ll featuretest.ll Message-ID: <200302262140.PAA02459@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: 2003-02-26-AccessSizeTest.ll added (r1.1) featuretest.ll updated: 1.4 -> 1.5 --- Log message: New testcase for size tracking brokenness --- Diffs of the changes: Index: llvm/test/Regression/Transforms/BasicAA/featuretest.ll diff -u llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.4 llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.5 --- llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.4 Tue Feb 25 15:43:37 2003 +++ llvm/test/Regression/Transforms/BasicAA/featuretest.ll Wed Feb 26 15:39:52 2003 @@ -62,3 +62,11 @@ %r = sub int %REMOVEu, %REMOVEv ret int %r } + +int %foo(int * %A) { + %X = load int* %A + %B = cast int* %A to sbyte* + %C = getelementptr sbyte* %B, long 4 + %Y = load sbyte* %C + ret int 8 +} From lattner at cs.uiuc.edu Wed Feb 26 15:58:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 15:58:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200302262157.PAA02809@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp updated: 1.2 -> 1.3 --- Log message: Fix bug: BasicAA/2003-02-26-AccessSizeTest.ll --- Diffs of the changes: Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.2 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.3 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.2 Wed Feb 26 15:28:49 2003 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Wed Feb 26 15:57:23 2003 @@ -142,19 +142,44 @@ std::swap(V1Size, V2Size); } - if (const GetElementPtrInst *GEP = dyn_cast(V1)) { - AliasResult R = alias(GEP->getOperand(0), V1Size, V2, V2Size); - if (R == NoAlias) return NoAlias; - if (R == MustAlias) { - // If there is at least one non-zero constant index, we know they cannot - // alias. - for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i) - if (const Constant *C = dyn_cast(GEP->getOperand(i))) - if (!C->isNullValue()) + if (V1Size != ~0U && V2Size != ~0U) + if (const GetElementPtrInst *GEP = dyn_cast(V1)) { + AliasResult R = alias(GEP->getOperand(0), V1Size, V2, V2Size); + if (R == NoAlias) return NoAlias; + if (R == MustAlias) { + // If there is at least one non-zero constant index, we know they cannot + // alias. + bool ConstantFound = false; + for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i) + if (const Constant *C = dyn_cast(GEP->getOperand(i))) + if (!C->isNullValue()) { + ConstantFound = true; + break; + } + if (ConstantFound) { + if (V2Size <= 1 && V1Size <= 1) // Just pointer check? return NoAlias; + + // Otherwise we have to check to see that the distance is more than + // the size of the argument... build an index vector that is equal to + // the arguments provided, except substitute 0's for any variable + // indexes we find... + + std::vector Indices; + Indices.reserve(GEP->getNumOperands()-1); + for (unsigned i = 1; i != GEP->getNumOperands(); ++i) + if (const Constant *C = dyn_cast(GEP->getOperand(i))) + Indices.push_back((Value*)C); + else + Indices.push_back(Constant::getNullValue(Type::LongTy)); + const Type *Ty = GEP->getOperand(0)->getType(); + int Offset = getTargetData().getIndexedOffset(Ty, Indices); + if (Offset >= (int)V2Size || Offset <= -(int)V1Size) + return NoAlias; + } + } } - } - + return MayAlias; } From lattner at cs.uiuc.edu Wed Feb 26 16:03:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 16:03:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/featuretest.ll Message-ID: <200302262202.QAA02838@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: featuretest.ll updated: 1.5 -> 1.6 --- Log message: Fix test --- Diffs of the changes: Index: llvm/test/Regression/Transforms/BasicAA/featuretest.ll diff -u llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.5 llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.6 --- llvm/test/Regression/Transforms/BasicAA/featuretest.ll:1.5 Wed Feb 26 15:39:52 2003 +++ llvm/test/Regression/Transforms/BasicAA/featuretest.ll Wed Feb 26 16:01:58 2003 @@ -63,7 +63,9 @@ ret int %r } -int %foo(int * %A) { +; Test that we can do funny pointer things and that distance calc will still +; work. +int %gep_distance_test3(int * %A) { %X = load int* %A %B = cast int* %A to sbyte* %C = getelementptr sbyte* %B, long 4 From lattner at cs.uiuc.edu Wed Feb 26 16:12:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 16:12:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/AliasSetTracker.h Message-ID: <200302262211.QAA02887@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: AliasSetTracker.h updated: 1.2 -> 1.3 --- Log message: Make the aliassettracker much more precise by actually tracking size information for various accesses. What a concept. --- Diffs of the changes: Index: llvm/include/llvm/Analysis/AliasSetTracker.h diff -u llvm/include/llvm/Analysis/AliasSetTracker.h:1.2 llvm/include/llvm/Analysis/AliasSetTracker.h:1.3 --- llvm/include/llvm/Analysis/AliasSetTracker.h:1.2 Mon Feb 24 14:37:52 2003 +++ llvm/include/llvm/Analysis/AliasSetTracker.h Wed Feb 26 16:10:55 2003 @@ -29,12 +29,19 @@ class PointerRec { HashNodePair *NextInList; AliasSet *AS; + unsigned Size; public: - PointerRec() : NextInList(0), AS(0) {} + PointerRec() : NextInList(0), AS(0), Size(0) {} HashNodePair *getNext() const { return NextInList; } bool hasAliasSet() const { return AS != 0; } + void updateSize(unsigned NewSize) { + if (NewSize > Size) Size = NewSize; + } + + unsigned getSize() const { return Size; } + AliasSet *getAliasSet(AliasSetTracker &AST) { assert(AS && "No AliasSet yet!"); if (AS->Forward) { @@ -87,7 +94,7 @@ unsigned AliasTy : 1; /// Define an iterator for alias sets... this is just a forward iterator. - class iterator : public forward_iterator { + class iterator : public forward_iterator { HashNodePair *CurNode; public: iterator(HashNodePair *CN = 0) : CurNode(CN) {} @@ -102,11 +109,11 @@ return *this; } - value_type operator*() const { + value_type &operator*() const { assert(CurNode && "Dereferencing AliasSet.end()!"); - return CurNode->first; + return *CurNode; } - value_type operator->() const { return operator*(); } + value_type *operator->() const { return &operator*(); } iterator& operator++() { // Preincrement assert(CurNode && "Advancing past AliasSet.end()!"); @@ -148,8 +155,8 @@ AliasSet() : PtrListHead(0), PtrListTail(0), Forward(0), RefCount(0), AccessTy(NoModRef), AliasTy(MustAlias) { } - Value *getSomePointer() const { - return PtrListHead ? PtrListHead->first : 0; + HashNodePair *getSomePointer() const { + return PtrListHead ? PtrListHead : 0; } /// getForwardedTarget - Return the real alias set this represents. If this @@ -170,13 +177,13 @@ void removeFromTracker(AliasSetTracker &AST); - void addPointer(AliasSetTracker &AST, HashNodePair &Entry); + void addPointer(AliasSetTracker &AST, HashNodePair &Entry, unsigned Size); void addCallSite(CallSite CS); /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// - bool aliasesPointer(const Value *Ptr, AliasAnalysis &AA) const; + bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const; bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; }; @@ -219,7 +226,7 @@ /// getAliasSetForPointer - Return the alias set that the specified pointer /// lives in... - AliasSet &getAliasSetForPointer(Value *P); + AliasSet &getAliasSetForPointer(Value *P, unsigned Size); /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -248,11 +255,11 @@ AliasSet::PointerRec())).first; } - void addPointer(Value *P, AliasSet::AccessType E) { - AliasSet &AS = getAliasSetForPointer(P); + void addPointer(Value *P, unsigned Size, AliasSet::AccessType E) { + AliasSet &AS = getAliasSetForPointer(P, Size); AS.AccessTy |= E; } - AliasSet *findAliasSetForPointer(const Value *Ptr); + AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size); AliasSet *findAliasSetForCallSite(CallSite CS); }; From lattner at cs.uiuc.edu Wed Feb 26 16:12:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 16:12:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/AliasSetTracker.cpp Message-ID: <200302262211.QAA02894@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: AliasSetTracker.cpp updated: 1.3 -> 1.4 --- Log message: Make the aliassettracker much more precise by actually tracking size information for various accesses. What a concept. --- Diffs of the changes: Index: llvm/lib/Analysis/AliasSetTracker.cpp diff -u llvm/lib/Analysis/AliasSetTracker.cpp:1.3 llvm/lib/Analysis/AliasSetTracker.cpp:1.4 --- llvm/lib/Analysis/AliasSetTracker.cpp:1.3 Wed Feb 26 13:28:57 2003 +++ llvm/lib/Analysis/AliasSetTracker.cpp Wed Feb 26 16:11:00 2003 @@ -10,11 +10,10 @@ #include "llvm/iOther.h" #include "llvm/iTerminators.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetData.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/InstIterator.h" -// FIXME: This should keep sizes associated with pointers! - /// mergeSetIn - Merge the specified alias set into this alias set... /// void AliasSet::mergeSetIn(AliasSet &AS) { @@ -54,17 +53,25 @@ AST.removeAliasSet(this); } -void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry){ +void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry, + unsigned Size) { assert(!Entry.second.hasAliasSet() && "Entry already in set!"); AliasAnalysis &AA = AST.getAliasAnalysis(); if (isMustAlias()) // Check to see if we have to downgrade to _may_ alias - if (Value *V = getSomePointer()) - if (AA.alias(V, ~0, Entry.first, ~0) == AliasAnalysis::MayAlias) + if (HashNodePair *P = getSomePointer()) { + AliasAnalysis::AliasResult Result = + AA.alias(P->first, P->second.getSize(), Entry.first, Size); + if (Result == AliasAnalysis::MayAlias) AliasTy = MayAlias; + else // First entry of must alias must have maximum size! + P->second.updateSize(Size); + assert(Result != AliasAnalysis::NoAlias && "Cannot be part of must set!"); + } Entry.second.setAliasSet(this); + Entry.second.updateSize(Size); // Add it to the end of the list... if (PtrListTail) @@ -77,27 +84,28 @@ void AliasSet::addCallSite(CallSite CS) { CallSites.push_back(CS); - AliasTy = MayAlias; // FIXME: Too conservative + AliasTy = MayAlias; // FIXME: Too conservative? } /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// -bool AliasSet::aliasesPointer(const Value *Ptr, AliasAnalysis &AA) const { +bool AliasSet::aliasesPointer(const Value *Ptr, unsigned Size, + AliasAnalysis &AA) const { if (AliasTy == MustAlias) { assert(CallSites.empty() && "Illegal must alias set!"); // If this is a set of MustAliases, only check to see if the pointer aliases // SOME value in the set... - Value *SomePtr = getSomePointer(); + HashNodePair *SomePtr = getSomePointer(); assert(SomePtr && "Empty must-alias set??"); - return AA.alias(SomePtr, ~0, Ptr, ~0); + return AA.alias(SomePtr->first, SomePtr->second.getSize(), Ptr, Size); } // If this is a may-alias set, we have to check all of the pointers in the set // to be sure it doesn't alias the set... for (iterator I = begin(), E = end(); I != E; ++I) - if (AA.alias(Ptr, ~0, *I, ~0)) + if (AA.alias(Ptr, Size, I->first, I->second.getSize())) return true; // Check the call sites list and invoke list... @@ -118,10 +126,11 @@ /// instruction referring to the pointer into. If there are multiple alias sets /// that may alias the pointer, merge them together and return the unified set. /// -AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr) { +AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr, + unsigned Size) { AliasSet *FoundSet = 0; for (iterator I = begin(), E = end(); I != E; ++I) - if (!I->Forward && I->aliasesPointer(Ptr, AA)) { + if (!I->Forward && I->aliasesPointer(Ptr, Size, AA)) { if (FoundSet == 0) { // If this is the first alias set ptr can go into... FoundSet = I; // Remember it. } else { // Otherwise, we must merge the sets... @@ -151,31 +160,34 @@ /// getAliasSetForPointer - Return the alias set that the specified pointer /// lives in... -AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer) { +AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, unsigned Size){ AliasSet::HashNodePair &Entry = getEntryFor(Pointer); // Check to see if the pointer is already known... - if (Entry.second.hasAliasSet()) { + if (Entry.second.hasAliasSet() && Size <= Entry.second.getSize()) { // Return the set! return *Entry.second.getAliasSet(*this)->getForwardedTarget(*this); - } else if (AliasSet *AS = findAliasSetForPointer(Pointer)) { + } else if (AliasSet *AS = findAliasSetForPointer(Pointer, Size)) { // Add it to the alias set it aliases... - AS->addPointer(*this, Entry); + AS->addPointer(*this, Entry, Size); return *AS; } else { // Otherwise create a new alias set to hold the loaded pointer... AliasSets.push_back(AliasSet()); - AliasSets.back().addPointer(*this, Entry); + AliasSets.back().addPointer(*this, Entry, Size); return AliasSets.back(); } } void AliasSetTracker::add(LoadInst *LI) { - addPointer(LI->getOperand(0), AliasSet::Refs); + addPointer(LI->getOperand(0), + AA.getTargetData().getTypeSize(LI->getType()), AliasSet::Refs); } void AliasSetTracker::add(StoreInst *SI) { - addPointer(SI->getOperand(1), AliasSet::Mods); + addPointer(SI->getOperand(1), + AA.getTargetData().getTypeSize(SI->getOperand(0)->getType()), + AliasSet::Mods); } void AliasSetTracker::add(CallSite CS) { @@ -221,7 +233,8 @@ OS << "Pointers: "; for (iterator I = begin(), E = end(); I != E; ++I) { if (I != begin()) OS << ", "; - WriteAsOperand(OS, *I); + WriteAsOperand(OS << "(", I->first); + OS << ", " << I->second.getSize() << ")"; } } if (!CallSites.empty()) { From lattner at cs.uiuc.edu Wed Feb 26 17:17:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 17:17:06 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-26-LoopExitNotDominated.ll Message-ID: <200302262316.RAA06426@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-26-LoopExitNotDominated.ll added (r1.1) --- Log message: New testcase crashing LICM --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Feb 26 18:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 18:38:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200302270037.SAA07351@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.20 -> 1.21 --- Log message: * LoopInfo now keeps track of exit blocks from the loop * New LoopInfo::isLoopHeader method * Remove some #if 0 code --- Diffs of the changes: Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.20 llvm/include/llvm/Analysis/LoopInfo.h:1.21 --- llvm/include/llvm/Analysis/LoopInfo.h:1.20 Fri Oct 11 00:31:10 2002 +++ llvm/include/llvm/Analysis/LoopInfo.h Wed Feb 26 18:37:22 2003 @@ -1,9 +1,17 @@ //===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator --------*- C++ -*--=// // // This file defines the LoopInfo class that is used to identify natural loops -// and determine the loop depth of various nodes of the CFG. Note that the -// loops identified may actually be several natural loops that share the same -// header node... not just a single natural loop. +// and determine the loop depth of various nodes of the CFG. Note that natural +// loops may actually be several loops that share the same header node... +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the function, the basic blocks the make up the +// loop, the nesting depth of the loop, and the successor blocks of the loop. +// +// It can calculate on the fly a variety of different bits of information, such +// as whether there is a preheader for the loop, the number of back edges to the +// header, and whether or not a particular block branches out of the loop. // //===----------------------------------------------------------------------===// @@ -22,8 +30,9 @@ /// class Loop { Loop *ParentLoop; - std::vector Blocks; // First entry is the header node std::vector SubLoops; // Loops contained entirely within this one + std::vector Blocks; // First entry is the header node + std::vector ExitBlocks; // Reachable blocks outside the loop unsigned LoopDepth; // Nesting depth of this loop Loop(const Loop &); // DO NOT IMPLEMENT @@ -39,14 +48,25 @@ /// getSubLoops - Return the loops contained entirely within this loop /// - inline const std::vector &getSubLoops() const { return SubLoops; } - inline const std::vector &getBlocks() const { return Blocks; } + const std::vector &getSubLoops() const { return SubLoops; } + + /// getBlocks - Get a list of the basic blocks which make up this loop. + /// + const std::vector &getBlocks() const { return Blocks; } + + /// getExitBlocks - Return all of the successor blocks of this loop. These + /// are the blocks _outside of the current loop_ which are branched to. + /// + const std::vector &getExitBlocks() const { return ExitBlocks; } /// isLoopExit - True if terminator in the block can branch to another block - /// that is outside of the current loop. + /// that is outside of the current loop. The reached block should be in the + /// ExitBlocks list. + /// bool isLoopExit(const BasicBlock *BB) const; - /// Find number of back edges + /// getNumBackEdges - Calculate the number of back edges to the loop header + /// unsigned getNumBackEdges() const; /// getLoopPreheader - If there is a preheader for this loop, return it. A @@ -61,14 +81,20 @@ /// BasicBlock *getLoopPreheader() const; - /// addBasicBlockToLoop - This function is used by other analyses to update - /// loop information. NewBB is set to be a new member of the current loop. + /// addBasicBlockToLoop - This method is used by other analyses to update loop + /// information. NewBB is set to be a new member of the current loop. /// Because of this, it is added as a member of all parent loops, and is added /// to the specified LoopInfo object as being in the current basic block. It /// is not valid to replace the loop header with this method. /// void addBasicBlockToLoop(BasicBlock *NewBB, LoopInfo &LI); + /// changeExitBlock - This method is used to update loop information. One + /// instance of the specified Old basic block is removed from the exit list + /// and replaced with New. + /// + void changeExitBlock(BasicBlock *Old, BasicBlock *New); + void print(std::ostream &O) const; private: friend class LoopInfo; @@ -124,14 +150,10 @@ return L ? L->getLoopDepth() : 0; } -#if 0 // isLoopHeader - True if the block is a loop header node bool isLoopHeader(BasicBlock *BB) const { return getLoopFor(BB)->getHeader() == BB; } - // isLoopEnd - True if block jumps to loop entry - bool isLoopEnd(BasicBlock *BB) const; -#endif /// runOnFunction - Calculate the natural loop information. /// From lattner at cs.uiuc.edu Wed Feb 26 18:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Feb 26 18:39:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200302270038.SAA07364@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.30 -> 1.31 --- Log message: - LoopInfo now calculates and tracks loop exit blocks --- Diffs of the changes: Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.30 llvm/lib/Analysis/LoopInfo.cpp:1.31 --- llvm/lib/Analysis/LoopInfo.cpp:1.30 Sat Feb 22 15:33:11 2003 +++ llvm/lib/Analysis/LoopInfo.cpp Wed Feb 26 18:38:34 2003 @@ -27,24 +27,24 @@ bool Loop::isLoopExit(const BasicBlock *BB) const { for (BasicBlock::succ_const_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) { - if (! contains(*SI)) + if (!contains(*SI)) return true; } return false; } unsigned Loop::getNumBackEdges() const { - unsigned numBackEdges = 0; - BasicBlock *header = Blocks.front(); + unsigned NumBackEdges = 0; + BasicBlock *H = getHeader(); for (std::vector::const_iterator I = Blocks.begin(), - E = Blocks.end(); I != E; ++I) { + E = Blocks.end(); I != E; ++I) for (BasicBlock::succ_iterator SI = succ_begin(*I), SE = succ_end(*I); SI != SE; ++SI) - if (header == *SI) - ++numBackEdges; - } - return numBackEdges; + if (*SI == H) + ++NumBackEdges; + + return NumBackEdges; } void Loop::print(std::ostream &OS) const { @@ -52,8 +52,16 @@ for (unsigned i = 0; i < getBlocks().size(); ++i) { if (i) OS << ","; - WriteAsOperand(OS, (const Value*)getBlocks()[i]); + WriteAsOperand(OS, getBlocks()[i], false); + } + if (!ExitBlocks.empty()) { + OS << "\tExitBlocks: "; + for (unsigned i = 0; i < getExitBlocks().size(); ++i) { + if (i) OS << ","; + WriteAsOperand(OS, getExitBlocks()[i], false); + } } + OS << "\n"; for (unsigned i = 0, e = getSubLoops().size(); i != e; ++i) @@ -131,9 +139,9 @@ BasicBlock *X = TodoStack.back(); TodoStack.pop_back(); - if (!L->contains(X)) { // As of yet unprocessed?? + if (!L->contains(X)) { // As of yet unprocessed?? L->Blocks.push_back(X); - + // Add all of the predecessors of X to the end of the work stack... TodoStack.insert(TodoStack.end(), pred_begin(X), pred_end(X)); } @@ -158,6 +166,14 @@ BBMap.insert(BBMI, std::make_pair(*I, L)); // Must be at this level } + // Now that we know all of the blocks that make up this loop, see if there are + // any branches to outside of the loop... building the ExitBlocks list. + for (std::vector::iterator BI = L->Blocks.begin(), + BE = L->Blocks.end(); BI != BE; ++BI) + for (succ_iterator I = succ_begin(*BI), E = succ_end(*BI); I != E; ++I) + if (!L->contains(*I)) // Not in current loop? + L->ExitBlocks.push_back(*I); // It must be an exit block... + return L; } @@ -210,4 +226,17 @@ L->Blocks.push_back(NewBB); L = L->getParentLoop(); } +} + +/// changeExitBlock - This method is used to update loop information. One +/// instance of the specified Old basic block is removed from the exit list +/// and replaced with New. +/// +void Loop::changeExitBlock(BasicBlock *Old, BasicBlock *New) { + assert(Old != New && "Cannot changeExitBlock to the same thing!"); + assert(Old && New && "Cannot changeExitBlock to or from a null node!"); + std::vector::iterator I = + std::find(ExitBlocks.begin(), ExitBlocks.end(), Old); + assert(I != ExitBlocks.end() && "Old exit block not found!"); + *I = New; } From lattner at cs.uiuc.edu Thu Feb 27 14:25:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 14:25:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200302272024.OAA18930@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.30 -> 1.31 --- Log message: Make the interface to update a little more efficient --- Diffs of the changes: Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.30 llvm/include/llvm/Analysis/Dominators.h:1.31 --- llvm/include/llvm/Analysis/Dominators.h:1.30 Wed Oct 30 20:39:48 2002 +++ llvm/include/llvm/Analysis/Dominators.h Thu Feb 27 14:24:17 2003 @@ -378,24 +378,26 @@ virtual void releaseMemory() { Frontiers.clear(); } // Accessor interface: + typedef DomSetMapType::iterator iterator; typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } const_iterator end() const { return Frontiers.end(); } - const_iterator find(BasicBlock* B) const { return Frontiers.find(B); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } void addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { assert(find(BB) == end() && "Block already in DominanceFrontier!"); Frontiers.insert(std::make_pair(BB, frontier)); } - void addToFrontier(BasicBlock *BB, BasicBlock *Node) { - DomSetMapType::iterator I = Frontiers.find(BB); + void addToFrontier(iterator I, BasicBlock *Node) { assert(I != end() && "BB is not in DominanceFrontier!"); I->second.insert(Node); } - void removeFromFrontier(BasicBlock *BB, BasicBlock *Node) { - DomSetMapType::iterator I = Frontiers.find(BB); + void removeFromFrontier(iterator I, BasicBlock *Node) { assert(I != end() && "BB is not in DominanceFrontier!"); assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); I->second.erase(Node); From lattner at cs.uiuc.edu Thu Feb 27 14:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 14:28:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302272027.OAA19006@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.4 -> 1.5 --- Log message: * Significant changes to the preheader insertion pass: - Now we perform loop exit-block splitting to ensure exit blocks are always dominated by the loop header. - We now preserve dominance frontier information - This fixes bug: LICM/2003-02-26-LoopExitNotDominated.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.4 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.5 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.4 Tue Oct 1 17:38:41 2002 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Thu Feb 27 14:27:08 2003 @@ -1,7 +1,20 @@ //===- LoopPreheaders.cpp - Loop Preheader Insertion Pass -----------------===// // -// Insert Loop pre-headers into the CFG for each function in the module. This -// pass updates loop information and dominator information. +// Insert Loop pre-headers and exit blocks into the CFG for each function in the +// module. This pass updates loop information and dominator information. +// +// Loop pre-header insertion guarantees that there is a single, non-critical +// entry edge from outside of the loop to the loop header. This simplifies a +// number of analyses and transformations, such as LICM. +// +// Loop exit-block insertion guarantees that all exit blocks from the loop +// (blocks which are outside of the loop that have predecessors inside of the +// loop) are dominated by the loop header. This simplifies transformations such +// as store-sinking that is built into LICM. +// +// Note that the simplifycfg pass will clean up blocks which are split out but +// end up being unneccesary, so usage of this pass does not neccesarily +// pessimize generated code. // //===----------------------------------------------------------------------===// @@ -13,6 +26,7 @@ #include "llvm/iPHINode.h" #include "llvm/Constant.h" #include "llvm/Support/CFG.h" +#include "Support/SetOperations.h" #include "Support/Statistic.h" namespace { @@ -24,15 +38,20 @@ virtual void getAnalysisUsage(AnalysisUsage &AU) const { // We need loop information to identify the loops... AU.addRequired(); + AU.addRequired(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); AU.addPreservedID(BreakCriticalEdgesID); // No crit edges added.... } private: bool ProcessLoop(Loop *L); + BasicBlock *SplitBlockPredecessors(BasicBlock *BB, const char *Suffix, + const std::vector &Preds); + void RewriteLoopExitBlock(Loop *L, BasicBlock *Exit); void InsertPreheaderForLoop(Loop *L); }; @@ -71,53 +90,54 @@ Changed = true; } + DominatorSet &DS = getAnalysis(); + BasicBlock *Header = L->getHeader(); + for (unsigned i = 0, e = L->getExitBlocks().size(); i != e; ++i) + if (!DS.dominates(Header, L->getExitBlocks()[i])) { + RewriteLoopExitBlock(L, L->getExitBlocks()[i]); + NumInserted++; + Changed = true; + } + const std::vector &SubLoops = L->getSubLoops(); for (unsigned i = 0, e = SubLoops.size(); i != e; ++i) Changed |= ProcessLoop(SubLoops[i]); return Changed; } - -/// InsertPreheaderForLoop - Once we discover that a loop doesn't have a -/// preheader, this method is called to insert one. This method has two phases: -/// preheader insertion and analysis updating. +/// SplitBlockPredecessors - Split the specified block into two blocks. We want +/// to move the predecessors specified in the Preds list to point to the new +/// block, leaving the remaining predecessors pointing to BB. This method +/// updates the SSA PHINode's, but no other analyses. /// -void Preheaders::InsertPreheaderForLoop(Loop *L) { - BasicBlock *Header = L->getHeader(); - - // Compute the set of predecessors of the loop that are not in the loop. - std::vector OutsideBlocks; - for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); - PI != PE; ++PI) - if (!L->contains(*PI)) // Coming in from outside the loop? - OutsideBlocks.push_back(*PI); // Keep track of it... - - assert(OutsideBlocks.size() != 1 && "Loop already has a preheader!"); +BasicBlock *Preheaders::SplitBlockPredecessors(BasicBlock *BB, + const char *Suffix, + const std::vector &Preds) { - // Create new basic block, insert right before the header of the loop... - BasicBlock *NewBB = new BasicBlock(Header->getName()+".preheader", Header); + // Create new basic block, insert right before the original block... + BasicBlock *NewBB = new BasicBlock(BB->getName()+Suffix, BB); // The preheader first gets an unconditional branch to the loop header... - BranchInst *BI = new BranchInst(Header); + BranchInst *BI = new BranchInst(BB); NewBB->getInstList().push_back(BI); - // For every PHI node in the loop body, insert a PHI node into NewBB where - // the incoming values from the out of loop edges are moved to NewBB. We - // have two possible cases here. If the loop is dead, we just insert dummy - // entries into the PHI nodes for the new edge. If the loop is not dead, we - // move the incoming edges in Header into new PHI nodes in NewBB. + // For every PHI node in the block, insert a PHI node into NewBB where the + // incoming values from the out of loop edges are moved to NewBB. We have two + // possible cases here. If the loop is dead, we just insert dummy entries + // into the PHI nodes for the new edge. If the loop is not dead, we move the + // incoming edges in BB into new PHI nodes in NewBB. // - if (!OutsideBlocks.empty()) { // Is the loop not obviously dead? - for (BasicBlock::iterator I = Header->begin(); + if (!Preds.empty()) { // Is the loop not obviously dead? + for (BasicBlock::iterator I = BB->begin(); PHINode *PN = dyn_cast(&*I); ++I) { // Create the new PHI node, insert it into NewBB at the end of the block PHINode *NewPHI = new PHINode(PN->getType(), PN->getName()+".ph", BI); // Move all of the edges from blocks outside the loop to the new PHI - for (unsigned i = 0, e = OutsideBlocks.size(); i != e; ++i) { - Value *V = PN->removeIncomingValue(OutsideBlocks[i]); - NewPHI->addIncoming(V, OutsideBlocks[i]); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + Value *V = PN->removeIncomingValue(Preds[i]); + NewPHI->addIncoming(V, Preds[i]); } // Add an incoming value to the PHI node in the loop for the preheader @@ -126,23 +146,45 @@ } // Now that the PHI nodes are updated, actually move the edges from - // OutsideBlocks to point to NewBB instead of Header. + // Preds to point to NewBB instead of BB. // - for (unsigned i = 0, e = OutsideBlocks.size(); i != e; ++i) { - TerminatorInst *TI = OutsideBlocks[i]->getTerminator(); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + TerminatorInst *TI = Preds[i]->getTerminator(); for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) - if (TI->getSuccessor(s) == Header) + if (TI->getSuccessor(s) == BB) TI->setSuccessor(s, NewBB); } } else { // Otherwise the loop is dead... - for (BasicBlock::iterator I = Header->begin(); + for (BasicBlock::iterator I = BB->begin(); PHINode *PN = dyn_cast(&*I); ++I) // Insert dummy values as the incoming value... PN->addIncoming(Constant::getNullValue(PN->getType()), NewBB); - } + } + return NewBB; +} + +/// InsertPreheaderForLoop - Once we discover that a loop doesn't have a +/// preheader, this method is called to insert one. This method has two phases: +/// preheader insertion and analysis updating. +/// +void Preheaders::InsertPreheaderForLoop(Loop *L) { + BasicBlock *Header = L->getHeader(); + // Compute the set of predecessors of the loop that are not in the loop. + std::vector OutsideBlocks; + for (pred_iterator PI = pred_begin(Header), PE = pred_end(Header); + PI != PE; ++PI) + if (!L->contains(*PI)) // Coming in from outside the loop? + OutsideBlocks.push_back(*PI); // Keep track of it... + + assert(OutsideBlocks.size() != 1 && "Loop already has a preheader!"); + + // Split out the loop pre-header + BasicBlock *NewBB = + SplitBlockPredecessors(Header, ".preheader", OutsideBlocks); + //===--------------------------------------------------------------------===// // Update analysis results now that we have preformed the transformation // @@ -151,20 +193,20 @@ if (Loop *Parent = L->getParentLoop()) Parent->addBasicBlockToLoop(NewBB, getAnalysis()); - // Update dominator information if it is around... - if (DominatorSet *DS = getAnalysisToUpdate()) { + DominatorSet &DS = getAnalysis(); // Update dominator info + { // The blocks that dominate NewBB are the blocks that dominate Header, // minus Header, plus NewBB. - DominatorSet::DomSetType DomSet = DS->getDominators(Header); + DominatorSet::DomSetType DomSet = DS.getDominators(Header); DomSet.insert(NewBB); // We dominate ourself DomSet.erase(Header); // Header does not dominate us... - DS->addBasicBlock(NewBB, DomSet); + DS.addBasicBlock(NewBB, DomSet); // The newly created basic block dominates all nodes dominated by Header. for (Function::iterator I = Header->getParent()->begin(), E = Header->getParent()->end(); I != E; ++I) - if (DS->dominates(Header, I)) - DS->addDominator(I, NewBB); + if (DS.dominates(Header, I)) + DS.addDominator(I, NewBB); } // Update immediate dominator information if we have it... @@ -187,5 +229,140 @@ // Change the header node so that PNHode is the new immediate dominator DT->changeImmediateDominator(HeaderNode, PHNode); + } + + // Update dominance frontier information... + if (DominanceFrontier *DF = getAnalysisToUpdate()) { + // The DF(NewBB) is just (DF(Header)-Header), because NewBB dominates + // everything that Header does, and it strictly dominates Header in + // addition. + assert(DF->find(Header) != DF->end() && "Header node doesn't have DF set?"); + DominanceFrontier::DomSetType NewDFSet = DF->find(Header)->second; + NewDFSet.erase(Header); + DF->addBasicBlock(NewBB, NewDFSet); + + // Now we must loop over all of the dominance frontiers in the function, + // replacing occurances of Header with NewBB in some cases. If a block + // dominates a (now) predecessor of NewBB, but did not strictly dominate + // Header, it will have Header in it's DF set, but should now have NewBB in + // its set. + for (unsigned i = 0, e = OutsideBlocks.size(); i != e; ++i) { + // Get all of the dominators of the predecessor... + const DominatorSet::DomSetType &PredDoms = + DS.getDominators(OutsideBlocks[i]); + for (DominatorSet::DomSetType::const_iterator PDI = PredDoms.begin(), + PDE = PredDoms.end(); PDI != PDE; ++PDI) { + BasicBlock *PredDom = *PDI; + // If the loop header is in DF(PredDom), then PredDom didn't dominate + // the header but did dominate a predecessor outside of the loop. Now + // we change this entry to include the preheader in the DF instead of + // the header. + DominanceFrontier::iterator DFI = DF->find(PredDom); + assert(DFI != DF->end() && "No dominance frontier for node?"); + if (DFI->second.count(Header)) { + DF->removeFromFrontier(DFI, Header); + DF->addToFrontier(DFI, NewBB); + } + } + } + } +} + +void Preheaders::RewriteLoopExitBlock(Loop *L, BasicBlock *Exit) { + DominatorSet &DS = getAnalysis(); + assert(!DS.dominates(L->getHeader(), Exit) && + "Loop already dominates exit block??"); + + std::vector LoopBlocks; + for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit); I != E; ++I) + if (L->contains(*I)) + LoopBlocks.push_back(*I); + + BasicBlock *NewBB = + SplitBlockPredecessors(Exit, ".loopexit", LoopBlocks); + + // Update dominator information... The blocks that dominate NewBB are the + // intersection of the dominators of predecessors, plus the block itself. + // The newly created basic block does not dominate anything except itself. + // + DominatorSet::DomSetType NewBBDomSet = DS.getDominators(LoopBlocks[0]); + for (unsigned i = 1, e = LoopBlocks.size(); i != e; ++i) + set_intersect(NewBBDomSet, DS.getDominators(LoopBlocks[i])); + NewBBDomSet.insert(NewBB); // All blocks dominate themselves... + DS.addBasicBlock(NewBB, NewBBDomSet); + + // Update immediate dominator information if we have it... + BasicBlock *NewBBIDom = 0; + if (ImmediateDominators *ID = getAnalysisToUpdate()) { + // This block does not strictly dominate anything, so it is not an immediate + // dominator. To find the immediate dominator of the new exit node, we + // trace up the immediate dominators of a predecessor until we find a basic + // block that dominates the exit block. + // + BasicBlock *Dom = LoopBlocks[0]; // Some random predecessor... + while (!NewBBDomSet.count(Dom)) { // Loop until we find a dominator... + assert(Dom != 0 && "No shared dominator found???"); + Dom = ID->get(Dom); + } + + // Set the immediate dominator now... + ID->addNewBlock(NewBB, Dom); + NewBBIDom = Dom; // Reuse this if calculating DominatorTree info... + } + + // Update DominatorTree information if it is active. + if (DominatorTree *DT = getAnalysisToUpdate()) { + // NewBB doesn't dominate anything, so just create a node and link it into + // its immediate dominator. If we don't have ImmediateDominator info + // around, calculate the idom as above. + DominatorTree::Node *NewBBIDomNode; + if (NewBBIDom) { + NewBBIDomNode = DT->getNode(NewBBIDom); + } else { + NewBBIDomNode = DT->getNode(LoopBlocks[0]); // Random pred + while (!NewBBDomSet.count(NewBBIDomNode->getNode())) { + NewBBIDomNode = NewBBIDomNode->getIDom(); + assert(NewBBIDomNode && "No shared dominator found??"); + } + } + + // Create the new dominator tree node... + DT->createNewNode(NewBB, NewBBIDomNode); + } + + // Update dominance frontier information... + if (DominanceFrontier *DF = getAnalysisToUpdate()) { + // DF(NewBB) is {Exit} because NewBB does not strictly dominate Exit, but it + // does dominate itself (and there is an edge (NewBB -> Exit)). + DominanceFrontier::DomSetType NewDFSet; + NewDFSet.insert(Exit); + DF->addBasicBlock(NewBB, NewDFSet); + + // Now we must loop over all of the dominance frontiers in the function, + // replacing occurances of Exit with NewBB in some cases. If a block + // dominates a (now) predecessor of NewBB, but did not strictly dominate + // Exit, it will have Exit in it's DF set, but should now have NewBB in its + // set. + for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) { + // Get all of the dominators of the predecessor... + const DominatorSet::DomSetType &PredDoms =DS.getDominators(LoopBlocks[i]); + for (DominatorSet::DomSetType::const_iterator PDI = PredDoms.begin(), + PDE = PredDoms.end(); PDI != PDE; ++PDI) { + BasicBlock *PredDom = *PDI; + // Make sure to only rewrite blocks that are part of the loop... + if (L->contains(PredDom)) { + // If the exit node is in DF(PredDom), then PredDom didn't dominate + // Exit but did dominate a predecessor inside of the loop. Now we + // change this entry to include NewBB in the DF instead of Exit. + DominanceFrontier::iterator DFI = DF->find(PredDom); + assert(DFI != DF->end() && "No dominance frontier for node?"); + if (DFI->second.count(Exit)) { + DF->removeFromFrontier(DFI, Exit); + DF->addToFrontier(DFI, NewBB); + } + } + } + } + } } From lattner at cs.uiuc.edu Thu Feb 27 14:56:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 14:56:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionResolution.cpp Message-ID: <200302272055.OAA19567@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionResolution.cpp updated: 1.21 -> 1.22 --- Log message: Replace assertion with a handler. --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionResolution.cpp diff -u llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.21 llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.22 --- llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.21 Fri Feb 14 13:12:29 2003 +++ llvm/lib/Transforms/IPO/FunctionResolution.cpp Thu Feb 27 14:55:48 2003 @@ -47,7 +47,6 @@ // Keep an iterator to where we want to insert cast instructions if the // argument types don't agree. // - BasicBlock::iterator BBI = CI; unsigned NumArgsToCopy = CI->getNumOperands()-1; if (NumArgsToCopy != ParamTys.size() && !(NumArgsToCopy > ParamTys.size() && @@ -72,7 +71,7 @@ if (i-1 < ParamTys.size() && V->getType() != ParamTys[i-1]) { // Must insert a cast... - V = new CastInst(V, ParamTys[i-1], "argcast", BBI); + V = new CastInst(V, ParamTys[i-1], "argcast", CI); } Params.push_back(V); @@ -81,20 +80,18 @@ // Replace the old call instruction with a new call instruction that calls // the real function. // - Instruction *NewCall = new CallInst(Dest, Params, "", BBI); - - // Remove the old call instruction from the program... - BB->getInstList().remove(BBI); + Instruction *NewCall = new CallInst(Dest, Params, "", CI); + std::string Name = CI->getName(); CI->setName(""); // Transfer the name over... if (NewCall->getType() != Type::VoidTy) - NewCall->setName(CI->getName()); + NewCall->setName(Name); // Replace uses of the old instruction with the appropriate values... // if (NewCall->getType() == CI->getType()) { CI->replaceAllUsesWith(NewCall); - NewCall->setName(CI->getName()); + NewCall->setName(Name); } else if (NewCall->getType() == Type::VoidTy) { // Resolved function does not return a value but the prototype does. This @@ -112,14 +109,13 @@ // if (!CI->use_empty()) { // Insert the new cast instruction... - CastInst *NewCast = new CastInst(NewCall, CI->getType(), - NewCall->getName(), BBI); + CastInst *NewCast = new CastInst(NewCall, CI->getType(), Name, CI); CI->replaceAllUsesWith(NewCast); } } // The old instruction is no longer needed, destroy it! - delete CI; + BB->getInstList().erase(CI); } @@ -132,14 +128,24 @@ const FunctionType *OldMT = Old->getFunctionType(); const FunctionType *ConcreteMT = Concrete->getFunctionType(); - assert(OldMT->getParamTypes().size() <= - ConcreteMT->getParamTypes().size() && - "Concrete type must have more specified parameters!"); + if (OldMT->getParamTypes().size() <= ConcreteMT->getParamTypes().size()) + if (!Old->use_empty()) { + std::cerr << "WARNING: Linking function '" << Old->getName() + << "' is causing arguments to be dropped.\n"; + std::cerr << "WARNING: Prototype: "; + WriteAsOperand(std::cerr, Old); + std::cerr << " resolved to "; + WriteAsOperand(std::cerr, Concrete); + std::cerr << "\n"; + } // Check to make sure that if there are specified types, that they // match... // - for (unsigned i = 0; i < OldMT->getParamTypes().size(); ++i) + unsigned NumArguments = std::min(OldMT->getParamTypes().size(), + ConcreteMT->getParamTypes().size()); + + for (unsigned i = 0; i < NumArguments; ++i) if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) { std::cerr << "funcresolve: Function [" << Old->getName() << "]: Parameter types conflict for: '" << OldMT From lattner at cs.uiuc.edu Thu Feb 27 15:40:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 15:40:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-27-PreheaderProblem.ll Message-ID: <200302272139.PAA21311@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-27-PreheaderProblem.ll added (r1.1) --- Log message: Testcase for Preheaders problem --- Diffs of the changes: From lattner at cs.uiuc.edu Thu Feb 27 15:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 15:51:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302272150.PAA21888@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.5 -> 1.6 --- Log message: * Don't forget to update Loop information! * Remove bogus assertion: there may be a single outside predecessor and still need a new loop-preheader if the predecessor has multiple successors. See bug: LICM/2003-02-27-PreheaderProblem.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.5 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.6 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.5 Thu Feb 27 14:27:08 2003 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Thu Feb 27 15:50:19 2003 @@ -179,8 +179,6 @@ if (!L->contains(*PI)) // Coming in from outside the loop? OutsideBlocks.push_back(*PI); // Keep track of it... - assert(OutsideBlocks.size() != 1 && "Loop already has a preheader!"); - // Split out the loop pre-header BasicBlock *NewBB = SplitBlockPredecessors(Header, ".preheader", OutsideBlocks); @@ -281,6 +279,11 @@ BasicBlock *NewBB = SplitBlockPredecessors(Exit, ".loopexit", LoopBlocks); + // Update Loop Information - we know that the new block will be in the parent + // loop of L. + if (Loop *Parent = L->getParentLoop()) + Parent->addBasicBlockToLoop(NewBB, getAnalysis()); + // Update dominator information... The blocks that dominate NewBB are the // intersection of the dominators of predecessors, plus the block itself. // The newly created basic block does not dominate anything except itself. @@ -363,6 +366,5 @@ } } } - } } From lattner at cs.uiuc.edu Thu Feb 27 15:52:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 15:52:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200302272151.PAA21900@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.31 -> 1.32 --- Log message: Fix bug: LICM/2003-02-27-PreheaderProblem.ll There may be a single outside predecessor and still need a new loop-preheader if the predecessor has multiple successors. --- Diffs of the changes: Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.31 llvm/lib/Analysis/LoopInfo.cpp:1.32 --- llvm/lib/Analysis/LoopInfo.cpp:1.31 Wed Feb 26 18:38:34 2003 +++ llvm/lib/Analysis/LoopInfo.cpp Thu Feb 27 15:51:38 2003 @@ -200,6 +200,13 @@ return 0; // Multiple predecessors outside the loop Out = *PI; } + + // Make sure there is only one exit out of the preheader... + succ_iterator SI = succ_begin(Out); + ++SI; + if (SI != succ_end(Out)) + return 0; // Multiple exits from the block, must not be a preheader. + // If there is exactly one preheader, return it. If there was zero, then Out // is still null. From lattner at cs.uiuc.edu Thu Feb 27 16:00:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:00:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-27-StoreSinkPHIs.ll Message-ID: <200302272159.PAA22192@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-27-StoreSinkPHIs.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: From lattner at cs.uiuc.edu Thu Feb 27 16:00:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:00:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp Message-ID: <200302272159.PAA22199@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.22 -> 1.23 --- Log message: Fix bug: 2003-02-27-StoreSinkPHIs.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.22 llvm/lib/Transforms/Scalar/LICM.cpp:1.23 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.22 Wed Feb 26 13:28:55 2003 +++ llvm/lib/Transforms/Scalar/LICM.cpp Thu Feb 27 15:59:36 2003 @@ -437,7 +437,10 @@ for (succ_iterator SI = succ_begin(*I), SE = succ_end(*I); SI != SE; ++SI) if (!CurLoop->contains(*SI)) { // Copy all of the allocas into their memory locations... - Instruction *InsertPos = (*SI)->begin(); + BasicBlock::iterator BI = (*SI)->begin(); + while (isa(*BI)) + ++BI; // Skip over all of the phi nodes in the block... + Instruction *InsertPos = BI; for (unsigned i = 0, e = PromotedValues.size(); i != e; ++i) { // Load from the alloca... LoadInst *LI = new LoadInst(PromotedValues[i].first, "", InsertPos); From lattner at cs.uiuc.edu Thu Feb 27 16:32:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:32:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302272231.QAA23678@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.6 -> 1.7 --- Log message: Add a new assertion to check that stuff is happening right Ironically the exit block modification code wasn't updating the exit block information itself. Fix this. --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.6 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.7 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.6 Thu Feb 27 15:50:19 2003 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Thu Feb 27 16:31:07 2003 @@ -95,6 +95,8 @@ for (unsigned i = 0, e = L->getExitBlocks().size(); i != e; ++i) if (!DS.dominates(Header, L->getExitBlocks()[i])) { RewriteLoopExitBlock(L, L->getExitBlocks()[i]); + assert(DS.dominates(Header, L->getExitBlocks()[i]) && + "RewriteLoopExitBlock failed?"); NumInserted++; Changed = true; } @@ -270,19 +272,22 @@ DominatorSet &DS = getAnalysis(); assert(!DS.dominates(L->getHeader(), Exit) && "Loop already dominates exit block??"); + assert(std::find(L->getExitBlocks().begin(), L->getExitBlocks().end(), Exit) + != L->getExitBlocks().end() && "Not a current exit block!"); std::vector LoopBlocks; for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit); I != E; ++I) if (L->contains(*I)) LoopBlocks.push_back(*I); - BasicBlock *NewBB = - SplitBlockPredecessors(Exit, ".loopexit", LoopBlocks); - + assert(!LoopBlocks.empty() && "No edges coming in from outside the loop?"); + BasicBlock *NewBB = SplitBlockPredecessors(Exit, ".loopexit", LoopBlocks); + // Update Loop Information - we know that the new block will be in the parent // loop of L. if (Loop *Parent = L->getParentLoop()) Parent->addBasicBlockToLoop(NewBB, getAnalysis()); + L->changeExitBlock(Exit, NewBB); // Update exit block information // Update dominator information... The blocks that dominate NewBB are the // intersection of the dominators of predecessors, plus the block itself. From lattner at cs.uiuc.edu Thu Feb 27 16:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:35:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-27-PreheaderExitNodeUpdate.ll Message-ID: <200302272234.QAA23790@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-27-PreheaderExitNodeUpdate.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: From lattner at cs.uiuc.edu Thu Feb 27 16:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:38:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200302272237.QAA23843@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.21 -> 1.22 --- Log message: Change behavior of changeExitBlock function to replace all instances of exit block --- Diffs of the changes: Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.21 llvm/include/llvm/Analysis/LoopInfo.h:1.22 --- llvm/include/llvm/Analysis/LoopInfo.h:1.21 Wed Feb 26 18:37:22 2003 +++ llvm/include/llvm/Analysis/LoopInfo.h Thu Feb 27 16:37:35 2003 @@ -89,8 +89,8 @@ /// void addBasicBlockToLoop(BasicBlock *NewBB, LoopInfo &LI); - /// changeExitBlock - This method is used to update loop information. One - /// instance of the specified Old basic block is removed from the exit list + /// changeExitBlock - This method is used to update loop information. All + /// instances of the specified Old basic block are removed from the exit list /// and replaced with New. /// void changeExitBlock(BasicBlock *Old, BasicBlock *New); From lattner at cs.uiuc.edu Thu Feb 27 16:38:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:38:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200302272237.QAA23851@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.32 -> 1.33 --- Log message: Change behavior of changeExitBlock function to replace all instances of exit block --- Diffs of the changes: Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.32 llvm/lib/Analysis/LoopInfo.cpp:1.33 --- llvm/lib/Analysis/LoopInfo.cpp:1.32 Thu Feb 27 15:51:38 2003 +++ llvm/lib/Analysis/LoopInfo.cpp Thu Feb 27 16:37:44 2003 @@ -235,8 +235,8 @@ } } -/// changeExitBlock - This method is used to update loop information. One -/// instance of the specified Old basic block is removed from the exit list +/// changeExitBlock - This method is used to update loop information. All +/// instances of the specified Old basic block are removed from the exit list /// and replaced with New. /// void Loop::changeExitBlock(BasicBlock *Old, BasicBlock *New) { @@ -246,4 +246,10 @@ std::find(ExitBlocks.begin(), ExitBlocks.end(), Old); assert(I != ExitBlocks.end() && "Old exit block not found!"); *I = New; + + I = std::find(I+1, ExitBlocks.end(), Old); + while (I != ExitBlocks.end()) { + *I = New; + I = std::find(I+1, ExitBlocks.end(), Old); + } } From lattner at cs.uiuc.edu Thu Feb 27 16:49:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:49:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200302272248.QAA24359@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.33 -> 1.34 --- Log message: Simplify a bit by using a new member function --- Diffs of the changes: Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.33 llvm/lib/Analysis/LoopInfo.cpp:1.34 --- llvm/lib/Analysis/LoopInfo.cpp:1.33 Thu Feb 27 16:37:44 2003 +++ llvm/lib/Analysis/LoopInfo.cpp Thu Feb 27 16:48:08 2003 @@ -242,12 +242,9 @@ void Loop::changeExitBlock(BasicBlock *Old, BasicBlock *New) { assert(Old != New && "Cannot changeExitBlock to the same thing!"); assert(Old && New && "Cannot changeExitBlock to or from a null node!"); - std::vector::iterator I = - std::find(ExitBlocks.begin(), ExitBlocks.end(), Old); - assert(I != ExitBlocks.end() && "Old exit block not found!"); - *I = New; - - I = std::find(I+1, ExitBlocks.end(), Old); + assert(hasExitBlock(Old) && "Old exit block not found!"); + std::vector::iterator + I = std::find(ExitBlocks.begin(), ExitBlocks.end(), Old); while (I != ExitBlocks.end()) { *I = New; I = std::find(I+1, ExitBlocks.end(), Old); From lattner at cs.uiuc.edu Thu Feb 27 16:49:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:49:03 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200302272248.QAA24372@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.22 -> 1.23 --- Log message: Add new Loop::hasExitBlock helper method --- Diffs of the changes: Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.22 llvm/include/llvm/Analysis/LoopInfo.h:1.23 --- llvm/include/llvm/Analysis/LoopInfo.h:1.22 Thu Feb 27 16:37:35 2003 +++ llvm/include/llvm/Analysis/LoopInfo.h Thu Feb 27 16:48:28 2003 @@ -69,6 +69,15 @@ /// unsigned getNumBackEdges() const; + /// hasExitBlock - Return true if the current loop has the specified block as + /// an exit block... + bool hasExitBlock(BasicBlock *BB) const { + for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) + if (ExitBlocks[i] == BB) + return true; + return false; + } + /// getLoopPreheader - If there is a preheader for this loop, return it. A /// loop has a preheader if there is only one edge to the header of the loop /// from outside of the loop. If this is the case, the block branching to the From lattner at cs.uiuc.edu Thu Feb 27 16:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 16:50:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302272249.QAA24382@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.7 -> 1.8 --- Log message: Fix bug: 2003-02-27-PreheaderExitNodeUpdate.ll by updating exit node info --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.7 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.8 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.7 Thu Feb 27 16:31:07 2003 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Thu Feb 27 16:48:57 2003 @@ -192,6 +192,22 @@ // We know that we have loop information to update... update it now. if (Loop *Parent = L->getParentLoop()) Parent->addBasicBlockToLoop(NewBB, getAnalysis()); + + // If the header for the loop used to be an exit node for another loop, then + // we need to update this to know that the loop-preheader is now the exit + // node. Note that the only loop that could have our header as an exit node + // is a sibling loop, ie, one with the same parent loop. + const std::vector *ParentSubLoops; + if (Loop *Parent = L->getParentLoop()) + ParentSubLoops = &Parent->getSubLoops(); + else // Must check top-level loops... + ParentSubLoops = &getAnalysis().getTopLevelLoops(); + + // Loop over all sibling loops, performing the substitution... + for (unsigned i = 0, e = ParentSubLoops->size(); i != e; ++i) + if ((*ParentSubLoops)[i]->hasExitBlock(Header)) + (*ParentSubLoops)[i]->changeExitBlock(Header, NewBB); + DominatorSet &DS = getAnalysis(); // Update dominator info { From lattner at cs.uiuc.edu Thu Feb 27 20:56:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 20:56:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-27-NestedLoopExitBlocks.ll Message-ID: <200302280255.UAA26898@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-27-NestedLoopExitBlocks.ll added (r1.1) --- Log message: New test --- Diffs of the changes: From lattner at cs.uiuc.edu Thu Feb 27 21:06:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 21:06:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200302280305.VAA27086@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.23 -> 1.24 --- Log message: Add graph traits specializations for loop nesting information... --- Diffs of the changes: Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.23 llvm/include/llvm/Analysis/LoopInfo.h:1.24 --- llvm/include/llvm/Analysis/LoopInfo.h:1.23 Thu Feb 27 16:48:28 2003 +++ llvm/include/llvm/Analysis/LoopInfo.h Thu Feb 27 21:05:15 2003 @@ -19,6 +19,7 @@ #define LLVM_ANALYSIS_LOOP_INFO_H #include "llvm/Pass.h" +#include "Support/GraphTraits.h" #include class DominatorSet; @@ -185,5 +186,32 @@ // Make sure that any clients of this file link in LoopInfo.cpp static IncludeFile LOOP_INFO_INCLUDE_FILE((void*)&LoopInfo::stub); + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits { + typedef const Loop NodeType; + typedef std::vector::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->getSubLoops().begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->getSubLoops().end(); + } +}; + +template <> struct GraphTraits { + typedef Loop NodeType; + typedef std::vector::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->getSubLoops().begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->getSubLoops().end(); + } +}; #endif From lattner at cs.uiuc.edu Thu Feb 27 21:09:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Feb 27 21:09:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302280308.VAA27168@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.8 -> 1.9 --- Log message: Fix bug: LICM/2003-02-27-PreheaderExitNodeUpdate.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.8 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.9 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.8 Thu Feb 27 16:48:57 2003 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Thu Feb 27 21:07:54 2003 @@ -28,6 +28,7 @@ #include "llvm/Support/CFG.h" #include "Support/SetOperations.h" #include "Support/Statistic.h" +#include "Support/DepthFirstIterator.h" namespace { Statistic<> NumInserted("preheaders", "Number of pre-header nodes inserted"); @@ -303,7 +304,10 @@ // loop of L. if (Loop *Parent = L->getParentLoop()) Parent->addBasicBlockToLoop(NewBB, getAnalysis()); - L->changeExitBlock(Exit, NewBB); // Update exit block information + + // Replace any instances of Exit with NewBB in this and any nested loops... + for (df_iterator I = df_begin(L), E = df_end(L); I != E; ++I) + I->changeExitBlock(Exit, NewBB); // Update exit block information // Update dominator information... The blocks that dominate NewBB are the // intersection of the dominators of predecessors, plus the block itself. From lattner at cs.uiuc.edu Fri Feb 28 10:14:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 10:14:01 2003 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/BugDriver.h CrashDebugger.cpp ExtractFunction.cpp Message-ID: <200302281613.KAA04086@apoc.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: BugDriver.h updated: 1.3 -> 1.4 CrashDebugger.cpp updated: 1.3 -> 1.4 ExtractFunction.cpp updated: 1.2 -> 1.3 --- Log message: * Reduce the number of useless bytecode files produced by bugpoint. - This also speeds it up as the bytecode writer isn't terribly fast. * Add a new cleanup pass after everything else to run -funcresolve -globaldce --- Diffs of the changes: Index: llvm/tools/bugpoint/BugDriver.h diff -u llvm/tools/bugpoint/BugDriver.h:1.3 llvm/tools/bugpoint/BugDriver.h:1.4 --- llvm/tools/bugpoint/BugDriver.h:1.3 Wed Jan 22 20:48:33 2003 +++ llvm/tools/bugpoint/BugDriver.h Fri Feb 28 10:13:20 2003 @@ -125,6 +125,12 @@ /// Module *deleteInstructionFromProgram(Instruction *I, unsigned Simp) const; + /// performFinalCleanups - This method clones the current Program and performs + /// a series of cleanups intended to get rid of extra cruft on the module + /// before handing it to the user... + /// + Module *performFinalCleanups() const; + /// initializeExecutionEnvironment - This method is used to set up the /// environment for executing LLVM programs. /// Index: llvm/tools/bugpoint/CrashDebugger.cpp diff -u llvm/tools/bugpoint/CrashDebugger.cpp:1.3 llvm/tools/bugpoint/CrashDebugger.cpp:1.4 --- llvm/tools/bugpoint/CrashDebugger.cpp:1.3 Wed Jan 22 20:48:33 2003 +++ llvm/tools/bugpoint/CrashDebugger.cpp Fri Feb 28 10:13:20 2003 @@ -84,6 +84,7 @@ /// bool BugDriver::debugPassCrash(const PassInfo *Pass) { EmitProgressBytecode(Pass, "passinput"); + bool Reduced = false, AnyReduction = false; if (CountFunctions(Program) > 1) { // Attempt to reduce the input program down to a single function that still @@ -106,7 +107,7 @@ // reduce the testcase... delete M; - EmitProgressBytecode(Pass, "reduced-"+I->getName()); + Reduced = AnyReduction = true; break; } @@ -122,6 +123,11 @@ } } + if (Reduced) { + EmitProgressBytecode(Pass, "reduced-function"); + Reduced = false; + } + // FIXME: This should attempt to delete entire basic blocks at a time to speed // up convergence... @@ -159,8 +165,8 @@ if (runPass(Pass)) { // Yup, it does, we delete the old module, and continue trying to // reduce the testcase... - EmitProgressBytecode(Pass, "reduced-" + I->getName()); delete M; + Reduced = AnyReduction = true; goto TryAgain; // I wish I had a multi-level break here! } @@ -171,6 +177,28 @@ } } } while (Simplification); - + + // Try to clean up the testcase by running funcresolve and globaldce... + if (AnyReduction) { + std::cout << "\n*** Attempting to perform final cleanups: "; + Module *M = performFinalCleanups(); + std::swap(Program, M); + + // Find out if the pass still crashes on the cleaned up program... + if (runPass(Pass)) { + // Yup, it does, keep the reduced version... + delete M; + Reduced = AnyReduction = true; + } else { + delete Program; // Otherwise, restore the original module... + Program = M; + } + } + + if (Reduced) { + EmitProgressBytecode(Pass, "reduced-simplified"); + Reduced = false; + } + return false; } Index: llvm/tools/bugpoint/ExtractFunction.cpp diff -u llvm/tools/bugpoint/ExtractFunction.cpp:1.2 llvm/tools/bugpoint/ExtractFunction.cpp:1.3 --- llvm/tools/bugpoint/ExtractFunction.cpp:1.2 Wed Jan 22 20:48:33 2003 +++ llvm/tools/bugpoint/ExtractFunction.cpp Fri Feb 28 10:13:20 2003 @@ -81,3 +81,16 @@ Passes.run(*Result); return Result; } + +/// performFinalCleanups - This method clones the current Program and performs +/// a series of cleanups intended to get rid of extra cruft on the module +/// before handing it to the user... +/// +Module *BugDriver::performFinalCleanups() const { + PassManager CleanupPasses; + CleanupPasses.add(createFunctionResolvingPass()); + CleanupPasses.add(createGlobalDCEPass()); + Module *M = CloneModule(Program); + CleanupPasses.run(*M); + return M; +} From lattner at cs.uiuc.edu Fri Feb 28 10:55:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 10:55:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Message-ID: <200302281654.KAA09074@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopPreheaders.cpp updated: 1.9 -> 1.10 --- Log message: Fix bug I introduced yesterday :( --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.9 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.10 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.9 Thu Feb 27 21:07:54 2003 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Fri Feb 28 10:54:17 2003 @@ -307,7 +307,8 @@ // Replace any instances of Exit with NewBB in this and any nested loops... for (df_iterator I = df_begin(L), E = df_end(L); I != E; ++I) - I->changeExitBlock(Exit, NewBB); // Update exit block information + if (I->hasExitBlock(Exit)) + I->changeExitBlock(Exit, NewBB); // Update exit block information // Update dominator information... The blocks that dominate NewBB are the // intersection of the dominators of predecessors, plus the block itself. From lattner at cs.uiuc.edu Fri Feb 28 10:55:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 10:55:04 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200302281654.KAA09396@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.24 -> 1.25 --- Log message: Add dump method for loops --- Diffs of the changes: Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.24 llvm/include/llvm/Analysis/LoopInfo.h:1.25 --- llvm/include/llvm/Analysis/LoopInfo.h:1.24 Thu Feb 27 21:05:15 2003 +++ llvm/include/llvm/Analysis/LoopInfo.h Fri Feb 28 10:54:37 2003 @@ -106,6 +106,7 @@ void changeExitBlock(BasicBlock *Old, BasicBlock *New); void print(std::ostream &O) const; + void dump() const; private: friend class LoopInfo; inline Loop(BasicBlock *BB) : ParentLoop(0) { From lattner at cs.uiuc.edu Fri Feb 28 10:55:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 10:55:07 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200302281654.KAA09586@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.34 -> 1.35 --- Log message: Add dump method for Loops --- Diffs of the changes: Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.34 llvm/lib/Analysis/LoopInfo.cpp:1.35 --- llvm/lib/Analysis/LoopInfo.cpp:1.34 Thu Feb 27 16:48:08 2003 +++ llvm/lib/Analysis/LoopInfo.cpp Fri Feb 28 10:54:45 2003 @@ -68,6 +68,10 @@ getSubLoops()[i]->print(OS); } +void Loop::dump() const { + print(std::cerr); +} + //===----------------------------------------------------------------------===// // LoopInfo implementation From lattner at cs.uiuc.edu Fri Feb 28 13:15:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:15:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll Message-ID: <200302281914.NAA15966@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-28-PromoteDifferentType.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: From lattner at cs.uiuc.edu Fri Feb 28 13:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:22:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Mem2Reg/DifferingTypes.ll Message-ID: <200302281921.NAA16199@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/Mem2Reg: DifferingTypes.ll added (r1.1) --- Log message: Add a test for a feature that I hope will be implemented someday --- Diffs of the changes: From lattner at cs.uiuc.edu Fri Feb 28 13:22:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:22:04 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll Message-ID: <200302281921.NAA16225@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LICM: 2003-02-28-PromoteDifferentType.ll updated: 1.1 -> 1.2 --- Log message: Fix testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll diff -u llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll:1.1 llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll:1.2 --- llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll:1.1 Fri Feb 28 13:13:58 2003 +++ llvm/test/Regression/Transforms/LICM/2003-02-28-PromoteDifferentType.ll Fri Feb 28 13:21:27 2003 @@ -8,7 +8,7 @@ store int 5, int* %P %P2 = cast int* %P to sbyte* store sbyte 4, sbyte* %P2 - br bool true, label %loop, label %Out + br bool true, label %Loop, label %Out Out: ret void } From lattner at cs.uiuc.edu Fri Feb 28 13:22:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:22:07 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp Message-ID: <200302281921.NAA16250@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.23 -> 1.24 --- Log message: Fix bug: LICM/2003-02-28-PromoteDifferentType.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.23 llvm/lib/Transforms/Scalar/LICM.cpp:1.24 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.23 Thu Feb 27 15:59:36 2003 +++ llvm/lib/Transforms/Scalar/LICM.cpp Fri Feb 28 13:21:40 2003 @@ -487,9 +487,15 @@ bool PointerOk = true; for (std::set::const_iterator I =CurLBI->LoadedPointers.begin(), - E = CurLBI->LoadedPointers.end(); I != E; ++I) - if (AA->alias(V, ~0, *I, ~0) == AliasAnalysis::MayAlias) { + E = CurLBI->LoadedPointers.end(); PointerOk && I != E; ++I) + switch (AA->alias(V, ~0, *I, ~0)) { + case AliasAnalysis::MustAlias: + if (V->getType() != (*I)->getType()) + PointerOk = false; + break; + case AliasAnalysis::MayAlias: PointerOk = false; + case AliasAnalysis::NoAlias: break; } From lattner at cs.uiuc.edu Fri Feb 28 13:40:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:40:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200302281939.NAA18051@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.35 -> 1.36 --- Log message: Allow the time limit to be specified on the commandline --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.35 llvm/test/Programs/Makefile.programs:1.36 --- llvm/test/Programs/Makefile.programs:1.35 Fri Feb 14 18:31:04 2003 +++ llvm/test/Programs/Makefile.programs Fri Feb 28 13:39:49 2003 @@ -58,11 +58,16 @@ # DIFFPROG - The program used to diff the output DIFFPROG = $(PROGDIR)/DiffOutput.sh +# RUNTIMELIMIT - The number of seconds we should wait before certain events +# timeout. This is overridable on the commandline. +# +RUNTIMELIMIT := 30 + # RUNSAFELY - This program simply runs another program. If the program works # correctly, this script has no effect, otherwise it will do things like print a # stack trace of a core dump. It always returns "successful" so that tests will # continue to be run. -ULIMIT := ulimit -t 30 +ULIMIT := ulimit -t $(RUNTIMELIMIT) RUNSAFELY = $(ULIMIT); $(PROGDIR)/RunSafely.sh # From lattner at cs.uiuc.edu Fri Feb 28 13:41:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 13:41:01 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTest.pl Message-ID: <200302281940.NAA18066@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTest.pl updated: 1.7 -> 1.8 --- Log message: Allow tests to run for 5 minutes before timing out. --- Diffs of the changes: Index: llvm/utils/NightlyTest.pl diff -u llvm/utils/NightlyTest.pl:1.7 llvm/utils/NightlyTest.pl:1.8 --- llvm/utils/NightlyTest.pl:1.7 Fri Jan 24 10:28:25 2003 +++ llvm/utils/NightlyTest.pl Fri Feb 28 13:40:05 2003 @@ -270,7 +270,7 @@ # Run the programs tests... creating a report.nightly.html file if (!$NOTEST) { system "gmake $MAKEOPTS report.nightly.html TEST=nightly " - . "> $Prefix-ProgramTest.txt 2>&1"; + . "RUNTIMELIMIT=300 > $Prefix-ProgramTest.txt 2>&1"; } else { system "gunzip $Prefix-ProgramTest.txt.gz"; } From lattner at cs.uiuc.edu Fri Feb 28 14:06:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 14:06:01 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTestTemplate.html Message-ID: <200302282005.OAA19514@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTestTemplate.html updated: 1.5 -> 1.6 --- Log message: Fix broken links --- Diffs of the changes: Index: llvm/utils/NightlyTestTemplate.html diff -u llvm/utils/NightlyTestTemplate.html:1.5 llvm/utils/NightlyTestTemplate.html:1.6 --- llvm/utils/NightlyTestTemplate.html:1.5 Sun Feb 2 11:02:20 2003 +++ llvm/utils/NightlyTestTemplate.html Fri Feb 28 14:05:20 2003 @@ -144,8 +144,8 @@ instead of executing the program.

    -A complete log of testing is available for -further analysis. +A complete log of testing is available +for further analysis.

    Programs/MultiSource

    From lattner at cs.uiuc.edu Fri Feb 28 14:09:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 14:09:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/DiffOutput.sh Message-ID: <200302282008.OAA20256@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: DiffOutput.sh updated: 1.4 -> 1.5 --- Log message: Avoid garbage output --- Diffs of the changes: Index: llvm/test/Programs/DiffOutput.sh diff -u llvm/test/Programs/DiffOutput.sh:1.4 llvm/test/Programs/DiffOutput.sh:1.5 --- llvm/test/Programs/DiffOutput.sh:1.4 Wed Jan 22 09:23:04 2003 +++ llvm/test/Programs/DiffOutput.sh Fri Feb 28 14:07:59 2003 @@ -12,7 +12,7 @@ DIFFOUTPUT=Output/$2.diff-$1 # Find gnu diff -if which gdiff +if which gdiff 2> /dev/null then DIFF=gdiff else From lattner at cs.uiuc.edu Fri Feb 28 14:31:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Feb 28 14:31:00 2003 Subject: [llvm-commits] CVS: llvm/utils/NightlyTest.pl Message-ID: <200302282030.OAA24500@apoc.cs.uiuc.edu> Changes in directory llvm/utils: NightlyTest.pl updated: 1.8 -> 1.9 --- Log message: * Don't run tests if compilation failed * Don't summarize tests if testing failed --- Diffs of the changes: Index: llvm/utils/NightlyTest.pl diff -u llvm/utils/NightlyTest.pl:1.8 llvm/utils/NightlyTest.pl:1.9 --- llvm/utils/NightlyTest.pl:1.8 Fri Feb 28 13:40:05 2003 +++ llvm/utils/NightlyTest.pl Fri Feb 28 14:30:20 2003 @@ -262,60 +262,77 @@ my $ModifiedFilesList = AddPreTag join "\n", keys %ModifiedFiles; my $RemovedFilesList = AddPreTag join "\n", keys %RemovedFiles; -# -# Run the nightly programs tests... -# -chdir "test/Programs" or die "Could not change into programs testdir!"; - -# Run the programs tests... creating a report.nightly.html file -if (!$NOTEST) { - system "gmake $MAKEOPTS report.nightly.html TEST=nightly " - . "RUNTIMELIMIT=300 > $Prefix-ProgramTest.txt 2>&1"; -} else { - system "gunzip $Prefix-ProgramTest.txt.gz"; -} +my $TestError = 1; +my $ProgramsTable; -my $ProgramsTable = ReadFile "report.nightly.html"; +# If we build the tree successfully, the nightly programs tests... +if ($BuildError eq "") { + chdir "test/Programs" or die "Could not change into programs testdir!"; + + # Run the programs tests... creating a report.nightly.html file + if (!$NOTEST) { + system "gmake $MAKEOPTS report.nightly.html TEST=nightly " + . "RUNTIMELIMIT=300 > $Prefix-ProgramTest.txt 2>&1"; + } else { + system "gunzip $Prefix-ProgramTest.txt.gz"; + } -# -# Create a list of the tests which were run... -# -system "grep -E 'TEST-(PASS|FAIL)' < $Prefix-ProgramTest.txt " - . "| sort > $Prefix-Tests.txt"; + if (`grep '^gmake: .*Error' $Prefix-ProgramTest.txt | wc -l` + 0) { + $TestError = 1; + $ProgramsTable = "

    Error running tests!

    "; + } else { + $TestError = 0; + $ProgramsTable = ReadFile "report.nightly.html"; -# Compress the test output -system "gzip $Prefix-ProgramTest.txt"; + # + # Create a list of the tests which were run... + # + system "grep -E 'TEST-(PASS|FAIL)' < $Prefix-ProgramTest.txt " + . "| sort > $Prefix-Tests.txt"; + } -my ($RTestsAdded, $RTestsRemoved) = DiffFiles "-Tests.txt"; + # Compress the test output + system "gzip $Prefix-ProgramTest.txt"; +} -my @RawTestsAddedArray = split '\n', $RTestsAdded; -my @RawTestsRemovedArray = split '\n', $RTestsRemoved; +my ($TestsAdded, $TestsRemoved, $TestsFixed, $TestsBroken) = ("","","",""); -my %OldTests = map {GetRegex('TEST-....: (.+)', $_)=>$_} @RawTestsRemovedArray; -my %NewTests = map {GetRegex('TEST-....: (.+)', $_)=>$_} @RawTestsAddedArray; +if ($TestError) { + $TestsAdded = "error testing
    "; + $TestsRemoved = "error testing
    "; + $TestsFixed = "error testing
    "; + $TestsBroken = "error testing
    "; +} else { + my ($RTestsAdded, $RTestsRemoved) = DiffFiles "-Tests.txt"; -my ($TestsAdded, $TestsRemoved, $TestsFixed, $TestsBroken) = ("","","",""); + my @RawTestsAddedArray = split '\n', $RTestsAdded; + my @RawTestsRemovedArray = split '\n', $RTestsRemoved; -foreach $Test (keys %NewTests) { - if (!exists $OldTests{$Test}) { # TestAdded if in New but not old - $TestsAdded = "$TestsAdded$Test\n"; - } else { - if ($OldTests{$Test} =~ /TEST-PASS/) { # Was the old one a pass? - $TestsBroken = "$TestsBroken$Test\n"; # New one must be a failure + my %OldTests = map {GetRegex('TEST-....: (.+)', $_)=>$_} + @RawTestsRemovedArray; + my %NewTests = map {GetRegex('TEST-....: (.+)', $_)=>$_} + @RawTestsAddedArray; + + foreach $Test (keys %NewTests) { + if (!exists $OldTests{$Test}) { # TestAdded if in New but not old + $TestsAdded = "$TestsAdded$Test\n"; } else { - $TestsFixed = "$TestsFixed$Test\n"; # No, new one is a pass. + if ($OldTests{$Test} =~ /TEST-PASS/) { # Was the old one a pass? + $TestsBroken = "$TestsBroken$Test\n"; # New one must be a failure + } else { + $TestsFixed = "$TestsFixed$Test\n"; # No, new one is a pass. + } } } -} -foreach $Test (keys %OldTests) { # TestRemoved if in Old but not New - $TestsRemoved = "$TestsRemoved$Test\n" if (!exists $NewTests{$Test}); -} - -$TestsAdded = AddPreTag $TestsAdded; -$TestsRemoved = AddPreTag $TestsRemoved; -$TestsFixed = AddPreTag $TestsFixed; -$TestsBroken = AddPreTag $TestsBroken; + foreach $Test (keys %OldTests) { # TestRemoved if in Old but not New + $TestsRemoved = "$TestsRemoved$Test\n" if (!exists $NewTests{$Test}); + } + $TestsAdded = AddPreTag $TestsAdded; + $TestsRemoved = AddPreTag $TestsRemoved; + $TestsFixed = AddPreTag $TestsFixed; + $TestsBroken = AddPreTag $TestsBroken; +} # # Get a list of the previous days that we can link to... From lattner at cs.uiuc.edu Sun Mar 2 17:44:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Mar 2 17:44:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200303022343.RAA31911@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp updated: 1.3 -> 1.4 --- Log message: Fix a problem with negative indexes --- Diffs of the changes: Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.3 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.4 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.3 Wed Feb 26 15:57:23 2003 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Sun Mar 2 17:43:34 2003 @@ -301,11 +301,11 @@ } } - unsigned Offset1 = getTargetData().getIndexedOffset(GEPPointerTy, Indices1); - unsigned Offset2 = getTargetData().getIndexedOffset(GEPPointerTy, Indices2); + int Offset1 = getTargetData().getIndexedOffset(GEPPointerTy, Indices1); + int Offset2 = getTargetData().getIndexedOffset(GEPPointerTy, Indices2); assert(Offset1 < Offset2 &&"There is at least one different constant here!"); - if (Offset2-Offset1 >= SizeMax) { + if ((unsigned)(Offset2-Offset1) >= SizeMax) { //std::cerr << "Determined that these two GEP's don't alias [" // << SizeMax << " bytes]: \n" << *GEP1 << *GEP2; return NoAlias;