From: Andrew Lenharth Date: Wed, 15 Mar 2006 04:04:21 +0000 (+0000) Subject: Handle one offset with growth case seen in povray. Namely, if we have an offset, X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4bebcdbca18899ae475b4d34888fd52431c11691;p=oota-llvm.git Handle one offset with growth case seen in povray. Namely, if we have an offset, and the offset lands at a field boundary in the old type, construct a new type, copying the fields masked by the offset from the old type, and unify with that. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26775 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index 25aadbafc2b..bd1757dcfd9 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -492,13 +492,51 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset, 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 > 256) { + 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(NewTy) && isa(Ty)) { + DEBUG(std::cerr << "Ty: " << *Ty << "\nNewTy: " << *NewTy << "@" << Offset << "\n"); + unsigned O = 0; + const StructType *STy = cast(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 nt; + for (unsigned x = 0; x < i; ++x) + nt.push_back(STy->getElementType(x)); + STy = cast(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); + } + 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 @@ -506,15 +544,6 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset, // 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;