CFLAndersAAResult::FunctionInfo::FunctionInfo(const ReachabilitySet &ReachSet, AliasAttrMap AMap) { // Populate AttrMap for (const auto &Mapping : AMap.mappings()) { auto IVal = Mapping.first; // AttrMap only cares about top-level values if (IVal.DerefLevel == 0) AttrMap[IVal.Val] = Mapping.second; } // Populate AliasMap for (const auto &OuterMapping : ReachSet.value_mappings()) { // AliasMap only cares about top-level values if (OuterMapping.first.DerefLevel > 0) continue; auto Val = OuterMapping.first.Val; auto &AliasList = AliasMap[Val]; for (const auto &InnerMapping : OuterMapping.second) { // Again, AliasMap only cares about top-level values if (InnerMapping.first.DerefLevel == 0) AliasList.push_back(InnerMapping.first.Val); } // Sort AliasList for faster lookup std::sort(AliasList.begin(), AliasList.end(), std::less<const Value *>()); } // TODO: Populate function summary here }
static void populateAliasMap(DenseMap<const Value *, std::vector<OffsetValue>> &AliasMap, const ReachabilitySet &ReachSet) { for (const auto &OuterMapping : ReachSet.value_mappings()) { // AliasMap only cares about top-level values if (OuterMapping.first.DerefLevel > 0) continue; auto Val = OuterMapping.first.Val; auto &AliasList = AliasMap[Val]; for (const auto &InnerMapping : OuterMapping.second) { // Again, AliasMap only cares about top-level values if (InnerMapping.first.DerefLevel == 0) AliasList.push_back(OffsetValue{InnerMapping.first.Val, UnknownOffset}); } // Sort AliasList for faster lookup llvm::sort(AliasList.begin(), AliasList.end()); } }
static void populateExternalRelations( SmallVectorImpl<ExternalRelation> &ExtRelations, const Function &Fn, const SmallVectorImpl<Value *> &RetVals, const ReachabilitySet &ReachSet) { // If a function only returns one of its argument X, then X will be both an // argument and a return value at the same time. This is an edge case that // needs special handling here. for (const auto &Arg : Fn.args()) { if (is_contained(RetVals, &Arg)) { auto ArgVal = InterfaceValue{Arg.getArgNo() + 1, 0}; auto RetVal = InterfaceValue{0, 0}; ExtRelations.push_back(ExternalRelation{ArgVal, RetVal, 0}); } } // Below is the core summary construction logic. // A naive solution of adding only the value aliases that are parameters or // return values in ReachSet to the summary won't work: It is possible that a // parameter P is written into an intermediate value I, and the function // subsequently returns *I. In that case, *I is does not value alias anything // in ReachSet, and the naive solution will miss a summary edge from (P, 1) to // (I, 1). // To account for the aforementioned case, we need to check each non-parameter // and non-return value for the possibility of acting as an intermediate. // 'ValueMap' here records, for each value, which InterfaceValues read from or // write into it. If both the read list and the write list of a given value // are non-empty, we know that a particular value is an intermidate and we // need to add summary edges from the writes to the reads. DenseMap<Value *, ValueSummary> ValueMap; for (const auto &OuterMapping : ReachSet.value_mappings()) { if (auto Dst = getInterfaceValue(OuterMapping.first, RetVals)) { for (const auto &InnerMapping : OuterMapping.second) { // If Src is a param/return value, we get a same-level assignment. if (auto Src = getInterfaceValue(InnerMapping.first, RetVals)) { // This may happen if both Dst and Src are return values if (*Dst == *Src) continue; if (hasReadOnlyState(InnerMapping.second)) ExtRelations.push_back(ExternalRelation{*Dst, *Src, UnknownOffset}); // No need to check for WriteOnly state, since ReachSet is symmetric } else { // If Src is not a param/return, add it to ValueMap auto SrcIVal = InnerMapping.first; if (hasReadOnlyState(InnerMapping.second)) ValueMap[SrcIVal.Val].FromRecords.push_back( ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); if (hasWriteOnlyState(InnerMapping.second)) ValueMap[SrcIVal.Val].ToRecords.push_back( ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); } } } } for (const auto &Mapping : ValueMap) { for (const auto &FromRecord : Mapping.second.FromRecords) { for (const auto &ToRecord : Mapping.second.ToRecords) { auto ToLevel = ToRecord.DerefLevel; auto FromLevel = FromRecord.DerefLevel; // Same-level assignments should have already been processed by now if (ToLevel == FromLevel) continue; auto SrcIndex = FromRecord.IValue.Index; auto SrcLevel = FromRecord.IValue.DerefLevel; auto DstIndex = ToRecord.IValue.Index; auto DstLevel = ToRecord.IValue.DerefLevel; if (ToLevel > FromLevel) SrcLevel += ToLevel - FromLevel; else DstLevel += FromLevel - ToLevel; ExtRelations.push_back(ExternalRelation{ InterfaceValue{SrcIndex, SrcLevel}, InterfaceValue{DstIndex, DstLevel}, UnknownOffset}); } } } // Remove duplicates in ExtRelations llvm::sort(ExtRelations.begin(), ExtRelations.end()); ExtRelations.erase(std::unique(ExtRelations.begin(), ExtRelations.end()), ExtRelations.end()); }