aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/VMCore/Type.cpp108
1 files changed, 67 insertions, 41 deletions
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 6a9da3a..02b723f 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -17,6 +17,7 @@
#include "llvm/Constants.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <iostream>
@@ -443,44 +444,76 @@ void DerivedType::dropAllTypeUses() {
}
}
+
+
+/// TypePromotionGraph and graph traits - this is designed to allow us to do
+/// efficient SCC processing of type graphs. This is the exact same as
+/// GraphTraits<Type*>, except that we pretend that concrete types have no
+/// children to avoid processing them.
+struct TypePromotionGraph {
+ Type *Ty;
+ TypePromotionGraph(Type *T) : Ty(T) {}
+};
+
+namespace llvm {
+ template <> struct GraphTraits<TypePromotionGraph> {
+ typedef Type NodeType;
+ typedef Type::subtype_iterator ChildIteratorType;
+
+ static inline NodeType *getEntryNode(TypePromotionGraph G) { return G.Ty; }
+ static inline ChildIteratorType child_begin(NodeType *N) {
+ if (N->isAbstract())
+ return N->subtype_begin();
+ else // No need to process children of concrete types.
+ return N->subtype_end();
+ }
+ static inline ChildIteratorType child_end(NodeType *N) {
+ return N->subtype_end();
+ }
+ };
+}
+
+
// PromoteAbstractToConcrete - This is a recursive function that walks a type
// graph calculating whether or not a type is abstract.
//
// This method returns true if the type is found to still be abstract.
//
-bool Type::PromoteAbstractToConcrete(void *Ptr) {
- if (!isAbstract()) // Base case for the recursion
- return false; // Primitive = leaf type
-
- if (isa<OpaqueType>(this)) // Base case for the recursion
- return true; // This whole type is abstract!
-
- /// KnownAbstractTypes - This set contains all of the types that we know for
- /// sure are abstract. Once we discover that a type really is abstract, we
- /// remember this so we don't have to do potentially exponential amounts of
- /// checking in some cases.
- std::set<Type*> &KnownAbstractTypes = *(std::set<Type*>*)Ptr;
- if (KnownAbstractTypes.count(this))
- return true; // We already know this type is abstract!
-
- // We have to guard against recursion. To do this, we temporarily mark this
- // type as concrete, so that if we get back to here recursively we will think
- // it's not abstract, and thus not scan it again.
- setAbstract(false);
-
- // Scan all of the sub-types. If any of them are abstract, than so is this
- // one!
- for (Type::subtype_iterator I = subtype_begin(), E = subtype_end();
- I != E; ++I)
- if (const_cast<Type*>(I->get())->PromoteAbstractToConcrete(Ptr)) {
- KnownAbstractTypes.insert(this);
- setAbstract(true); // Restore the abstract bit.
- return true; // This type is abstract if subtype is abstract!
+void Type::PromoteAbstractToConcrete() {
+ if (!isAbstract()) return;
+
+ scc_iterator<TypePromotionGraph> SI = scc_begin(TypePromotionGraph(this));
+ scc_iterator<TypePromotionGraph> SE = scc_end (TypePromotionGraph(this));
+
+ for (; SI != SE; ++SI) {
+ std::vector<Type*> &SCC = *SI;
+
+ // Concrete types are leaves in the tree. Since an SCC will either be all
+ // abstract or all concrete, we only need to check one type.
+ if (SCC[0]->isAbstract()) {
+ if (isa<OpaqueType>(SCC[0]))
+ return; // Not going to be concrete, sorry.
+
+ // If all of the children of all of the types in this SCC are concrete,
+ // then this SCC is now concrete as well. If not, neither this SCC, nor
+ // any parent SCCs will be concrete, so we might as well just exit.
+ for (unsigned i = 0, e = SCC.size(); i != e; ++i)
+ for (Type::subtype_iterator CI = SCC[i]->subtype_begin(),
+ E = SCC[i]->subtype_end(); CI != E; ++CI)
+ if ((*CI)->isAbstract())
+ return; // Not going to be concrete, sorry.
+
+ // Okay, we just discovered this whole SCC is now concrete, mark it as
+ // such!
+ for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
+ assert(SCC[i]->isAbstract() && "Why are we processing concrete types?");
+
+ SCC[i]->setAbstract(false);
+ // The type just became concrete, notify all users!
+ cast<DerivedType>(SCC[i])->notifyUsesThatTypeBecameConcrete();
+ }
}
-
- // Nothing looks abstract here. Restore the abstract flag.
- setAbstract(true);
- return false;
+ }
}
@@ -730,15 +763,8 @@ public:
// If the type is currently thought to be abstract, rescan all of our
// subtypes to see if the type has just become concrete!
- if (Ty->isAbstract()) {
- std::set<Type*> KnownAbstractTypes;
- if (!Ty->PromoteAbstractToConcrete(&KnownAbstractTypes))
- Ty->setAbstract(false);
-
- // If the type just became concrete, notify all users!
- if (!Ty->isAbstract())
- Ty->notifyUsesThatTypeBecameConcrete();
- }
+ if (Ty->isAbstract())
+ Ty->PromoteAbstractToConcrete();
}
void print(const char *Arg) const {