#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Timer.h"
+#include <iostream>
#include <algorithm>
using namespace llvm;
Statistic<> NumDNE ("dsa", "Number of nodes removed by reachability");
Statistic<> NumTrivialDNE ("dsa", "Number of nodes trivially removed");
Statistic<> NumTrivialGlobalDNE("dsa", "Number of globals trivially removed");
-};
+ static cl::opt<unsigned>
+ DSAFieldLimit("dsa-field-limit", cl::Hidden,
+ cl::desc("Number of fields to track before collapsing a node"),
+ cl::init(256));
+}
#if 0
#define TIME_REGION(VARNAME, DESC) \
// collapse it. This can occur for fortran common blocks, which have stupid
// things like { [100000000 x double], [1000000 x double] }.
unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift;
- if (NumFields > 256) {
+ if (NumFields > DSAFieldLimit) {
foldNodeCompletely();
return true;
}
return true;
}
- if (Offset) { // We could handle this case, but we don't for now...
+ // If this node would have to have an unreasonable number of fields, just
+ // collapse it. This can occur for fortran common blocks, which have stupid
+ // things like { [100000000 x double], [1000000 x double] }.
+ unsigned NumFields = (NewTySize+Offset+DS::PointerSize-1) >> DS::PointerShift;
+ if (NumFields > DSAFieldLimit) {
+ foldNodeCompletely();
+ return true;
+ }
+
+ if (Offset) {
+ //handle some common cases:
+ // Ty: struct { t1, t2, t3, t4, ..., tn}
+ // NewTy: struct { offset, stuff...}
+ // try merge with NewTy: struct {t1, t2, stuff...} if offset lands exactly on a field in Ty
+ if (isa<StructType>(NewTy) && isa<StructType>(Ty)) {
+ DEBUG(std::cerr << "Ty: " << *Ty << "\nNewTy: " << *NewTy << "@" << Offset << "\n");
+ unsigned O = 0;
+ const StructType *STy = cast<StructType>(Ty);
+ const StructLayout &SL = *TD.getStructLayout(STy);
+ unsigned i = SL.getElementContainingOffset(Offset);
+ //Either we hit it exactly or give up
+ if (SL.MemberOffsets[i] != Offset) {
+ if (FoldIfIncompatible) foldNodeCompletely();
+ return true;
+ }
+ std::vector<const Type*> nt;
+ for (unsigned x = 0; x < i; ++x)
+ nt.push_back(STy->getElementType(x));
+ STy = cast<StructType>(NewTy);
+ nt.insert(nt.end(), STy->element_begin(), STy->element_end());
+ //and merge
+ STy = StructType::get(nt);
+ DEBUG(std::cerr << "Trying with: " << *STy << "\n");
+ return mergeTypeInfo(STy, 0);
+ }
+
+ //Ty: struct { t1, t2, t3 ... tn}
+ //NewTy T offset x
+ //try merge with NewTy: struct : {t1, t2, T} if offset lands on a field in Ty
+ if (isa<StructType>(Ty)) {
+ DEBUG(std::cerr << "Ty: " << *Ty << "\nNewTy: " << *NewTy << "@" << Offset << "\n");
+ unsigned O = 0;
+ const StructType *STy = cast<StructType>(Ty);
+ const StructLayout &SL = *TD.getStructLayout(STy);
+ unsigned i = SL.getElementContainingOffset(Offset);
+ //Either we hit it exactly or give up
+ if (SL.MemberOffsets[i] != Offset) {
+ if (FoldIfIncompatible) foldNodeCompletely();
+ return true;
+ }
+ std::vector<const Type*> nt;
+ for (unsigned x = 0; x < i; ++x)
+ nt.push_back(STy->getElementType(x));
+ nt.push_back(NewTy);
+ //and merge
+ STy = StructType::get(nt);
+ DEBUG(std::cerr << "Trying with: " << *STy << "\n");
+ return mergeTypeInfo(STy, 0);
+ }
+
std::cerr << "UNIMP: Trying to merge a growth type into "
<< "offset != 0: Collapsing!\n";
+ abort();
if (FoldIfIncompatible) foldNodeCompletely();
return true;
+
}
+
// Okay, the situation is nice and simple, we are trying to merge a type in
// at offset 0 that is bigger than our current type. Implement this by
// switching to the new type and then merge in the smaller one, which should
// ok, it will collapse the node as appropriate.
//
- // If this node would have to have an unreasonable number of fields, just
- // collapse it. This can occur for fortran common blocks, which have stupid
- // things like { [100000000 x double], [1000000 x double] }.
- unsigned NumFields = (NewTySize+DS::PointerSize-1) >> DS::PointerShift;
- if (NumFields > 256) {
- foldNodeCompletely();
- return true;
- }
-
const Type *OldTy = Ty;
Ty = NewTy;
NodeType &= ~Array;
void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) {
if (NH.isNull()) return; // Nothing to do
+ if (isNodeCompletelyFolded())
+ Offset = 0;
+
DSNodeHandle &ExistingEdge = getLink(Offset);
if (!ExistingEdge.isNull()) {
// Merge the two nodes...