forked from OSchip/llvm-project
[CFLAA] Split out more things from CFLSteens. NFC.
"More things" = StratifiedAttrs and various bits like interprocedural summaries. Patch by Jia Chen. Differential Revision: http://reviews.llvm.org/D21964 llvm-svn: 274592
This commit is contained in:
parent
1ca8affb24
commit
e191996a57
|
@ -0,0 +1,105 @@
|
|||
#include "AliasAnalysisSummary.h"
|
||||
#include "llvm/IR/Argument.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace cflaa {
|
||||
|
||||
namespace {
|
||||
LLVM_CONSTEXPR unsigned AttrEscapedIndex = 0;
|
||||
LLVM_CONSTEXPR unsigned AttrUnknownIndex = 1;
|
||||
LLVM_CONSTEXPR unsigned AttrGlobalIndex = 2;
|
||||
LLVM_CONSTEXPR unsigned AttrCallerIndex = 3;
|
||||
LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 4;
|
||||
LLVM_CONSTEXPR unsigned AttrLastArgIndex = NumAliasAttrs;
|
||||
LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
|
||||
|
||||
// NOTE: These aren't AliasAttrs because bitsets don't have a constexpr
|
||||
// ctor for some versions of MSVC that we support. We could maybe refactor,
|
||||
// but...
|
||||
using AliasAttr = unsigned;
|
||||
LLVM_CONSTEXPR AliasAttr AttrNone = 0;
|
||||
LLVM_CONSTEXPR AliasAttr AttrEscaped = 1 << AttrEscapedIndex;
|
||||
LLVM_CONSTEXPR AliasAttr AttrUnknown = 1 << AttrUnknownIndex;
|
||||
LLVM_CONSTEXPR AliasAttr AttrGlobal = 1 << AttrGlobalIndex;
|
||||
LLVM_CONSTEXPR AliasAttr AttrCaller = 1 << AttrCallerIndex;
|
||||
LLVM_CONSTEXPR AliasAttr ExternalAttrMask =
|
||||
AttrEscaped | AttrUnknown | AttrGlobal;
|
||||
}
|
||||
|
||||
AliasAttrs getAttrNone() { return AttrNone; }
|
||||
|
||||
AliasAttrs getAttrUnknown() { return AttrUnknown; }
|
||||
bool hasUnknownAttr(AliasAttrs Attr) { return Attr.test(AttrUnknownIndex); }
|
||||
|
||||
AliasAttrs getAttrCaller() { return AttrCaller; }
|
||||
bool hasCallerAttr(AliasAttrs Attr) { return Attr.test(AttrCaller); }
|
||||
bool hasUnknownOrCallerAttr(AliasAttrs Attr) {
|
||||
return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
|
||||
}
|
||||
|
||||
AliasAttrs getAttrEscaped() { return AttrEscaped; }
|
||||
bool hasEscapedAttr(AliasAttrs Attr) { return Attr.test(AttrEscapedIndex); }
|
||||
|
||||
static AliasAttr argNumberToAttr(unsigned ArgNum) {
|
||||
if (ArgNum >= AttrMaxNumArgs)
|
||||
return AttrUnknown;
|
||||
// N.B. MSVC complains if we use `1U` here, since AliasAttr' ctor takes
|
||||
// an unsigned long long.
|
||||
return AliasAttr(1ULL << (ArgNum + AttrFirstArgIndex));
|
||||
}
|
||||
|
||||
AliasAttrs getGlobalOrArgAttrFromValue(const Value &Val) {
|
||||
if (isa<GlobalValue>(Val))
|
||||
return AttrGlobal;
|
||||
|
||||
if (auto *Arg = dyn_cast<Argument>(&Val))
|
||||
// Only pointer arguments should have the argument attribute,
|
||||
// because things can't escape through scalars without us seeing a
|
||||
// cast, and thus, interaction with them doesn't matter.
|
||||
if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
|
||||
return argNumberToAttr(Arg->getArgNo());
|
||||
return AttrNone;
|
||||
}
|
||||
|
||||
bool isGlobalOrArgAttr(AliasAttrs Attr) {
|
||||
return Attr.reset(AttrEscapedIndex)
|
||||
.reset(AttrUnknownIndex)
|
||||
.reset(AttrCallerIndex)
|
||||
.any();
|
||||
}
|
||||
|
||||
AliasAttrs getExternallyVisibleAttrs(AliasAttrs Attr) {
|
||||
return Attr & AliasAttrs(ExternalAttrMask);
|
||||
}
|
||||
|
||||
Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue IValue,
|
||||
CallSite CS) {
|
||||
auto Index = IValue.Index;
|
||||
auto Value = (Index == 0) ? CS.getInstruction() : CS.getArgument(Index - 1);
|
||||
if (Value->getType()->isPointerTy())
|
||||
return InstantiatedValue{Value, IValue.DerefLevel};
|
||||
return None;
|
||||
}
|
||||
|
||||
Optional<InstantiatedRelation>
|
||||
instantiateExternalRelation(ExternalRelation ERelation, CallSite CS) {
|
||||
auto From = instantiateInterfaceValue(ERelation.From, CS);
|
||||
if (!From)
|
||||
return None;
|
||||
auto To = instantiateInterfaceValue(ERelation.To, CS);
|
||||
if (!To)
|
||||
return None;
|
||||
return InstantiatedRelation{*From, *To};
|
||||
}
|
||||
|
||||
Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute EAttr,
|
||||
CallSite CS) {
|
||||
auto Value = instantiateInterfaceValue(EAttr.IValue, CS);
|
||||
if (!Value)
|
||||
return None;
|
||||
return InstantiatedAttr{*Value, EAttr.Attr};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
//=====- CFLSummary.h - Abstract stratified sets implementation. --------=====//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file defines various utility types and functions useful to
|
||||
/// summary-based alias analysis.
|
||||
///
|
||||
/// Summary-based analysis, also known as bottom-up analysis, is a style of
|
||||
/// interprocedrual static analysis that tries to analyze the callees before the
|
||||
/// callers get analyzed. The key idea of summary-based analysis is to first
|
||||
/// process each function indepedently, outline its behavior in a condensed
|
||||
/// summary, and then instantiate the summary at the callsite when the said
|
||||
/// function is called elsewhere. This is often in contrast to another style
|
||||
/// called top-down analysis, in which callers are always analyzed first before
|
||||
/// the callees.
|
||||
///
|
||||
/// In a summary-based analysis, functions must be examined independently and
|
||||
/// out-of-context. We have no information on the state of the memory, the
|
||||
/// arguments, the global values, and anything else external to the function. To
|
||||
/// carry out the analysis conservative assumptions have to be made about those
|
||||
/// external states. In exchange for the potential loss of precision, the
|
||||
/// summary we obtain this way is highly reusable, which makes the analysis
|
||||
/// easier to scale to large programs even if carried out context-sensitively.
|
||||
///
|
||||
/// Currently, all CFL-based alias analyses adopt the summary-based approach
|
||||
/// and therefore heavily rely on this header.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
|
||||
#define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
|
||||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include <bitset>
|
||||
|
||||
namespace llvm {
|
||||
namespace cflaa {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AliasAttr related stuffs
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// The number of attributes that AliasAttr should contain. Attributes are
|
||||
/// described below, and 32 was an arbitrary choice because it fits nicely in 32
|
||||
/// bits (because we use a bitset for AliasAttr).
|
||||
static const unsigned NumAliasAttrs = 32;
|
||||
|
||||
/// These are attributes that an alias analysis can use to mark certain special
|
||||
/// properties of a given pointer. Refer to the related functions below to see
|
||||
/// what kinds of attributes are currently defined.
|
||||
typedef std::bitset<NumAliasAttrs> AliasAttrs;
|
||||
|
||||
/// Attr represent whether the said pointer comes from an unknown source
|
||||
/// (such as opaque memory or an integer cast).
|
||||
AliasAttrs getAttrNone();
|
||||
|
||||
/// AttrUnknown represent whether the said pointer comes from a source not known
|
||||
/// to alias analyses (such as opaque memory or an integer cast).
|
||||
AliasAttrs getAttrUnknown();
|
||||
bool hasUnknownAttr(AliasAttrs);
|
||||
|
||||
/// AttrCaller represent whether the said pointer comes from a source not known
|
||||
/// to the current function but known to the caller. Values pointed to by the
|
||||
/// arguments of the current function have this attribute set
|
||||
AliasAttrs getAttrCaller();
|
||||
bool hasCallerAttr(AliasAttrs);
|
||||
bool hasUnknownOrCallerAttr(AliasAttrs);
|
||||
|
||||
/// AttrEscaped represent whether the said pointer comes from a known source but
|
||||
/// escapes to the unknown world (e.g. casted to an integer, or passed as an
|
||||
/// argument to opaque function). Unlike non-escaped pointers, escaped ones may
|
||||
/// alias pointers coming from unknown sources.
|
||||
AliasAttrs getAttrEscaped();
|
||||
bool hasEscapedAttr(AliasAttrs);
|
||||
|
||||
/// AttrGlobal represent whether the said pointer is a global value.
|
||||
/// AttrArg represent whether the said pointer is an argument, and if so, what
|
||||
/// index the argument has.
|
||||
AliasAttrs getGlobalOrArgAttrFromValue(const Value &);
|
||||
bool isGlobalOrArgAttr(AliasAttrs);
|
||||
|
||||
/// Given an AliasAttrs, return a new AliasAttrs that only contains attributes
|
||||
/// meaningful to the caller. This function is primarily used for
|
||||
/// interprocedural analysis
|
||||
/// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal,
|
||||
/// and AttrEscaped
|
||||
AliasAttrs getExternallyVisibleAttrs(AliasAttrs);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Function summary related stuffs
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// We use InterfaceValue to describe parameters/return value, as well as
|
||||
/// potential memory locations that are pointed to by parameters/return value,
|
||||
/// of a function.
|
||||
/// Index is an integer which represents a single parameter or a return value.
|
||||
/// When the index is 0, it refers to the return value. Non-zero index i refers
|
||||
/// to the i-th parameter.
|
||||
/// DerefLevel indicates the number of dereferences one must perform on the
|
||||
/// parameter/return value to get this InterfaceValue.
|
||||
struct InterfaceValue {
|
||||
unsigned Index;
|
||||
unsigned DerefLevel;
|
||||
};
|
||||
|
||||
inline bool operator==(InterfaceValue lhs, InterfaceValue rhs) {
|
||||
return lhs.Index == rhs.Index && lhs.DerefLevel == rhs.DerefLevel;
|
||||
}
|
||||
inline bool operator!=(InterfaceValue lhs, InterfaceValue rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// We use ExternalRelation to describe an externally visible aliasing relations
|
||||
/// between parameters/return value of a function.
|
||||
struct ExternalRelation {
|
||||
InterfaceValue From, To;
|
||||
};
|
||||
|
||||
/// We use ExternalAttribute to describe an externally visible AliasAttrs
|
||||
/// for parameters/return value.
|
||||
struct ExternalAttribute {
|
||||
InterfaceValue IValue;
|
||||
AliasAttrs Attr;
|
||||
};
|
||||
|
||||
/// This is the result of instantiating InterfaceValue at a particular callsite
|
||||
struct InstantiatedValue {
|
||||
Value *Val;
|
||||
unsigned DerefLevel;
|
||||
};
|
||||
Optional<InstantiatedValue> instantiateInterfaceValue(InterfaceValue, CallSite);
|
||||
|
||||
/// This is the result of instantiating ExternalRelation at a particular
|
||||
/// callsite
|
||||
struct InstantiatedRelation {
|
||||
InstantiatedValue From, To;
|
||||
};
|
||||
Optional<InstantiatedRelation> instantiateExternalRelation(ExternalRelation,
|
||||
CallSite);
|
||||
|
||||
/// This is the result of instantiating ExternalAttribute at a particular
|
||||
/// callsite
|
||||
struct InstantiatedAttr {
|
||||
InstantiatedValue IValue;
|
||||
AliasAttrs Attr;
|
||||
};
|
||||
Optional<InstantiatedAttr> instantiateExternalAttribute(ExternalAttribute,
|
||||
CallSite);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,14 +15,11 @@
|
|||
#ifndef LLVM_ANALYSIS_CFLGRAPH_H
|
||||
#define LLVM_ANALYSIS_CFLGRAPH_H
|
||||
|
||||
#include "StratifiedSets.h"
|
||||
#include "AliasAnalysisSummary.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
|
||||
namespace cflaa {
|
||||
|
||||
/// Edges can be one of four "weights" -- each weight must have an inverse
|
||||
/// weight (Assign has Assign; Reference has Dereference).
|
||||
enum class EdgeType {
|
||||
|
@ -62,7 +59,7 @@ class CFLGraph {
|
|||
|
||||
struct NodeInfo {
|
||||
EdgeList Edges;
|
||||
StratifiedAttrs Attr;
|
||||
AliasAttrs Attr;
|
||||
};
|
||||
|
||||
typedef DenseMap<Node, NodeInfo> NodeMap;
|
||||
|
@ -104,10 +101,12 @@ public:
|
|||
const_node_iterator;
|
||||
|
||||
bool addNode(Node N) {
|
||||
return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), 0})).second;
|
||||
return NodeImpls
|
||||
.insert(std::make_pair(N, NodeInfo{EdgeList(), getAttrNone()}))
|
||||
.second;
|
||||
}
|
||||
|
||||
void addAttr(Node N, StratifiedAttrs Attr) {
|
||||
void addAttr(Node N, AliasAttrs Attr) {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
Info->Attr |= Attr;
|
||||
|
@ -123,7 +122,7 @@ public:
|
|||
ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
|
||||
}
|
||||
|
||||
StratifiedAttrs attrFor(Node N) const {
|
||||
AliasAttrs attrFor(Node N) const {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
return Info->Attr;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "llvm/Analysis/CFLSteensAliasAnalysis.h"
|
||||
#include "CFLGraph.h"
|
||||
#include "StratifiedSets.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -67,39 +68,6 @@ CFLSteensAAResult::CFLSteensAAResult(CFLSteensAAResult &&Arg)
|
|||
: AAResultBase(std::move(Arg)), TLI(Arg.TLI) {}
|
||||
CFLSteensAAResult::~CFLSteensAAResult() {}
|
||||
|
||||
/// We use InterfaceValue to describe parameters/return value, as well as
|
||||
/// potential memory locations that are pointed to by parameters/return value,
|
||||
/// of a function.
|
||||
/// Index is an integer which represents a single parameter or a return value.
|
||||
/// When the index is 0, it refers to the return value. Non-zero index i refers
|
||||
/// to the i-th parameter.
|
||||
/// DerefLevel indicates the number of dereferences one must perform on the
|
||||
/// parameter/return value to get this InterfaceValue.
|
||||
struct InterfaceValue {
|
||||
unsigned Index;
|
||||
unsigned DerefLevel;
|
||||
};
|
||||
|
||||
bool operator==(InterfaceValue lhs, InterfaceValue rhs) {
|
||||
return lhs.Index == rhs.Index && lhs.DerefLevel == rhs.DerefLevel;
|
||||
}
|
||||
bool operator!=(InterfaceValue lhs, InterfaceValue rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// We use ExternalRelation to describe an externally visible aliasing relations
|
||||
/// between parameters/return value of a function.
|
||||
struct ExternalRelation {
|
||||
InterfaceValue From, To;
|
||||
};
|
||||
|
||||
/// We use ExternalAttribute to describe an externally visible StratifiedAttrs
|
||||
/// for parameters/return value.
|
||||
struct ExternalAttribute {
|
||||
InterfaceValue IValue;
|
||||
StratifiedAttrs Attr;
|
||||
};
|
||||
|
||||
/// Information we have about a function and would like to keep around.
|
||||
class CFLSteensAAResult::FunctionInfo {
|
||||
StratifiedSets<Value *> Sets;
|
||||
|
@ -135,26 +103,6 @@ const StratifiedIndex StratifiedLink::SetSentinel =
|
|||
std::numeric_limits<StratifiedIndex>::max();
|
||||
|
||||
namespace {
|
||||
/// StratifiedInfo Attribute things.
|
||||
LLVM_CONSTEXPR unsigned MaxStratifiedAttrIndex = NumStratifiedAttrs;
|
||||
LLVM_CONSTEXPR unsigned AttrEscapedIndex = 0;
|
||||
LLVM_CONSTEXPR unsigned AttrUnknownIndex = 1;
|
||||
LLVM_CONSTEXPR unsigned AttrGlobalIndex = 2;
|
||||
LLVM_CONSTEXPR unsigned AttrCallerIndex = 3;
|
||||
LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 4;
|
||||
LLVM_CONSTEXPR unsigned AttrLastArgIndex = MaxStratifiedAttrIndex;
|
||||
LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
|
||||
|
||||
// NOTE: These aren't StratifiedAttrs because bitsets don't have a constexpr
|
||||
// ctor for some versions of MSVC that we support. We could maybe refactor,
|
||||
// but...
|
||||
using StratifiedAttr = unsigned;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrEscaped = 1 << AttrEscapedIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrGlobal = 1 << AttrGlobalIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrCaller = 1 << AttrCallerIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr ExternalAttrMask =
|
||||
AttrEscaped | AttrUnknown | AttrGlobal;
|
||||
|
||||
/// The maximum number of arguments we can put into a summary.
|
||||
LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
|
||||
|
@ -163,23 +111,6 @@ LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
|
|||
/// represent that locally.
|
||||
enum class Level { Same, Above, Below };
|
||||
|
||||
// This is the result of instantiating InterfaceValue at a particular callsite
|
||||
struct InterprocNode {
|
||||
Value *Val;
|
||||
unsigned DerefLevel;
|
||||
};
|
||||
|
||||
// Interprocedural assignment edges that CFLGraph may not easily model
|
||||
struct InterprocEdge {
|
||||
InterprocNode From, To;
|
||||
};
|
||||
|
||||
// Interprocedural attribute tagging that CFLGraph may not easily model
|
||||
struct InterprocAttr {
|
||||
InterprocNode Node;
|
||||
StratifiedAttrs Attr;
|
||||
};
|
||||
|
||||
/// Gets the edges our graph should have, based on an Instruction*
|
||||
class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
|
||||
CFLSteensAAResult &AA;
|
||||
|
@ -189,8 +120,8 @@ class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
|
|||
SmallVectorImpl<Value *> &ReturnValues;
|
||||
SmallPtrSetImpl<Value *> &Externals;
|
||||
SmallPtrSetImpl<Value *> &Escapes;
|
||||
SmallVectorImpl<InterprocEdge> &InterprocEdges;
|
||||
SmallVectorImpl<InterprocAttr> &InterprocAttrs;
|
||||
SmallVectorImpl<InstantiatedRelation> &InstantiatedRelations;
|
||||
SmallVectorImpl<InstantiatedAttr> &InstantiatedAttrs;
|
||||
|
||||
static bool hasUsefulEdges(ConstantExpr *CE) {
|
||||
// ConstantExpr doesn't have terminators, invokes, or fences, so only needs
|
||||
|
@ -210,7 +141,7 @@ class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
|
|||
visitConstantExpr(CExpr);
|
||||
}
|
||||
|
||||
void addNodeWithAttr(Value *Val, StratifiedAttrs Attr) {
|
||||
void addNodeWithAttr(Value *Val, AliasAttrs Attr) {
|
||||
addNode(Val);
|
||||
Graph.addAttr(Val, Attr);
|
||||
}
|
||||
|
@ -229,11 +160,12 @@ public:
|
|||
CFLGraph &Graph, SmallVectorImpl<Value *> &ReturnValues,
|
||||
SmallPtrSetImpl<Value *> &Externals,
|
||||
SmallPtrSetImpl<Value *> &Escapes,
|
||||
SmallVectorImpl<InterprocEdge> &InterprocEdges,
|
||||
SmallVectorImpl<InterprocAttr> &InterprocAttrs)
|
||||
SmallVectorImpl<InstantiatedRelation> &InstantiatedRelations,
|
||||
SmallVectorImpl<InstantiatedAttr> &InstantiatedAttrs)
|
||||
: AA(AA), TLI(TLI), Graph(Graph), ReturnValues(ReturnValues),
|
||||
Externals(Externals), Escapes(Escapes), InterprocEdges(InterprocEdges),
|
||||
InterprocAttrs(InterprocAttrs) {}
|
||||
Externals(Externals), Escapes(Escapes),
|
||||
InstantiatedRelations(InstantiatedRelations),
|
||||
InstantiatedAttrs(InstantiatedAttrs) {}
|
||||
|
||||
void visitInstruction(Instruction &) {
|
||||
llvm_unreachable("Unsupported instruction encountered");
|
||||
|
@ -250,12 +182,12 @@ public:
|
|||
|
||||
void visitPtrToIntInst(PtrToIntInst &Inst) {
|
||||
auto *Ptr = Inst.getOperand(0);
|
||||
addNodeWithAttr(Ptr, AttrEscaped);
|
||||
addNodeWithAttr(Ptr, getAttrEscaped());
|
||||
}
|
||||
|
||||
void visitIntToPtrInst(IntToPtrInst &Inst) {
|
||||
auto *Ptr = &Inst;
|
||||
addNodeWithAttr(Ptr, AttrUnknown);
|
||||
addNodeWithAttr(Ptr, getAttrUnknown());
|
||||
}
|
||||
|
||||
void visitCastInst(CastInst &Inst) {
|
||||
|
@ -325,7 +257,7 @@ public:
|
|||
// 2. Increments (stores to) *Ptr by some target-specific amount.
|
||||
// For now, we'll handle this like a landingpad instruction (by placing the
|
||||
// result in its own group, and having that group alias externals).
|
||||
addNodeWithAttr(&Inst, AttrUnknown);
|
||||
addNodeWithAttr(&Inst, getAttrUnknown());
|
||||
}
|
||||
|
||||
static bool isFunctionExternal(Function *Fn) {
|
||||
|
@ -350,35 +282,22 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
auto InstantiateInterfaceIndex = [&CS](unsigned Index) {
|
||||
auto Value =
|
||||
(Index == 0) ? CS.getInstruction() : CS.getArgument(Index - 1);
|
||||
return Value->getType()->isPointerTy() ? Value : nullptr;
|
||||
};
|
||||
|
||||
for (auto *Fn : Fns) {
|
||||
auto &FnInfo = AA.ensureCached(Fn);
|
||||
assert(FnInfo.hasValue());
|
||||
|
||||
auto &RetParamRelations = FnInfo->getRetParamRelations();
|
||||
for (auto &Relation : RetParamRelations) {
|
||||
auto FromVal = InstantiateInterfaceIndex(Relation.From.Index);
|
||||
auto ToVal = InstantiateInterfaceIndex(Relation.To.Index);
|
||||
if (FromVal && ToVal) {
|
||||
auto FromLevel = Relation.From.DerefLevel;
|
||||
auto ToLevel = Relation.To.DerefLevel;
|
||||
InterprocEdges.push_back(
|
||||
InterprocEdge{InterprocNode{FromVal, FromLevel},
|
||||
InterprocNode{ToVal, ToLevel}});
|
||||
}
|
||||
auto IRelation = instantiateExternalRelation(Relation, CS);
|
||||
if (IRelation.hasValue())
|
||||
InstantiatedRelations.push_back(*IRelation);
|
||||
}
|
||||
|
||||
auto &RetParamAttributes = FnInfo->getRetParamAttributes();
|
||||
for (auto &Attribute : RetParamAttributes) {
|
||||
if (auto Val = InstantiateInterfaceIndex(Attribute.IValue.Index)) {
|
||||
InterprocAttrs.push_back(InterprocAttr{
|
||||
InterprocNode{Val, Attribute.IValue.DerefLevel}, Attribute.Attr});
|
||||
}
|
||||
auto IAttr = instantiateExternalAttribute(Attribute, CS);
|
||||
if (IAttr.hasValue())
|
||||
InstantiatedAttrs.push_back(*IAttr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,7 +341,7 @@ public:
|
|||
if (Inst->getType()->isPointerTy()) {
|
||||
auto *Fn = CS.getCalledFunction();
|
||||
if (Fn == nullptr || !Fn->doesNotAlias(0))
|
||||
Graph.addAttr(Inst, AttrUnknown);
|
||||
Graph.addAttr(Inst, getAttrUnknown());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,7 +366,7 @@ public:
|
|||
// Exceptions come from "nowhere", from our analysis' perspective.
|
||||
// So we place the instruction its own group, noting that said group may
|
||||
// alias externals
|
||||
addNodeWithAttr(&Inst, AttrUnknown);
|
||||
addNodeWithAttr(&Inst, getAttrUnknown());
|
||||
}
|
||||
|
||||
void visitInsertValueInst(InsertValueInst &Inst) {
|
||||
|
@ -495,8 +414,8 @@ class CFLGraphBuilder {
|
|||
// Auxiliary structures used by the builder
|
||||
SmallPtrSet<Value *, 8> ExternalValues;
|
||||
SmallPtrSet<Value *, 8> EscapedValues;
|
||||
SmallVector<InterprocEdge, 8> InterprocEdges;
|
||||
SmallVector<InterprocAttr, 8> InterprocAttrs;
|
||||
SmallVector<InstantiatedRelation, 8> InstantiatedRelations;
|
||||
SmallVector<InstantiatedAttr, 8> InstantiatedAttrs;
|
||||
|
||||
// Helper functions
|
||||
|
||||
|
@ -528,7 +447,7 @@ class CFLGraphBuilder {
|
|||
return;
|
||||
|
||||
GetEdgesVisitor(Analysis, TLI, Graph, ReturnedValues, ExternalValues,
|
||||
EscapedValues, InterprocEdges, InterprocAttrs)
|
||||
EscapedValues, InstantiatedRelations, InstantiatedAttrs)
|
||||
.visit(Inst);
|
||||
}
|
||||
|
||||
|
@ -560,11 +479,11 @@ public:
|
|||
const SmallPtrSet<Value *, 8> &getEscapedValues() const {
|
||||
return EscapedValues;
|
||||
}
|
||||
const SmallVector<InterprocEdge, 8> &getInterprocEdges() const {
|
||||
return InterprocEdges;
|
||||
const SmallVector<InstantiatedRelation, 8> &getInstantiatedRelations() const {
|
||||
return InstantiatedRelations;
|
||||
}
|
||||
const SmallVector<InterprocAttr, 8> &getInterprocAttrs() const {
|
||||
return InterprocAttrs;
|
||||
const SmallVector<InstantiatedAttr, 8> &getInstantiatedAttrs() const {
|
||||
return InstantiatedAttrs;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -573,20 +492,6 @@ public:
|
|||
// Function declarations that require types defined in the namespace above
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Given a StratifiedAttrs, returns true if it marks the corresponding values
|
||||
/// as globals or arguments
|
||||
static bool isGlobalOrArgAttr(StratifiedAttrs Attr);
|
||||
|
||||
/// Given a StratifiedAttrs, returns true if the corresponding values come from
|
||||
/// an unknown source (such as opaque memory or an integer cast)
|
||||
static bool isUnknownAttr(StratifiedAttrs Attr);
|
||||
|
||||
/// Given an argument number, returns the appropriate StratifiedAttr to set.
|
||||
static StratifiedAttrs argNumberToAttr(unsigned ArgNum);
|
||||
|
||||
/// Given a Value, potentially return which StratifiedAttr it maps to.
|
||||
static Optional<StratifiedAttrs> valueToAttr(Value *Val);
|
||||
|
||||
/// Gets the "Level" that one should travel in StratifiedSets
|
||||
/// given an EdgeType.
|
||||
static Level directionOfEdgeType(EdgeType);
|
||||
|
@ -617,38 +522,6 @@ static bool getPossibleTargets(CallSite CS,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool isGlobalOrArgAttr(StratifiedAttrs Attr) {
|
||||
return Attr.reset(AttrEscapedIndex)
|
||||
.reset(AttrUnknownIndex)
|
||||
.reset(AttrCallerIndex)
|
||||
.any();
|
||||
}
|
||||
|
||||
static bool isUnknownAttr(StratifiedAttrs Attr) {
|
||||
return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
|
||||
}
|
||||
|
||||
static Optional<StratifiedAttrs> valueToAttr(Value *Val) {
|
||||
if (isa<GlobalValue>(Val))
|
||||
return StratifiedAttrs(AttrGlobal);
|
||||
|
||||
if (auto *Arg = dyn_cast<Argument>(Val))
|
||||
// Only pointer arguments should have the argument attribute,
|
||||
// because things can't escape through scalars without us seeing a
|
||||
// cast, and thus, interaction with them doesn't matter.
|
||||
if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
|
||||
return argNumberToAttr(Arg->getArgNo());
|
||||
return None;
|
||||
}
|
||||
|
||||
static StratifiedAttrs argNumberToAttr(unsigned ArgNum) {
|
||||
if (ArgNum >= AttrMaxNumArgs)
|
||||
return AttrUnknown;
|
||||
// N.B. MSVC complains if we use `1U` here, since StratifiedAttrs' ctor takes
|
||||
// an unsigned long long.
|
||||
return StratifiedAttrs(1ULL << (ArgNum + AttrFirstArgIndex));
|
||||
}
|
||||
|
||||
static Level directionOfEdgeType(EdgeType Weight) {
|
||||
switch (Weight) {
|
||||
case EdgeType::Reference:
|
||||
|
@ -715,7 +588,7 @@ CFLSteensAAResult::FunctionInfo::FunctionInfo(
|
|||
|
||||
auto &Link = Sets.getLink(SetIndex);
|
||||
InterfaceMap.insert(std::make_pair(SetIndex, CurrValue));
|
||||
auto ExternalAttrs = Link.Attrs & StratifiedAttrs(ExternalAttrMask);
|
||||
auto ExternalAttrs = getExternallyVisibleAttrs(Link.Attrs);
|
||||
if (ExternalAttrs.any())
|
||||
RetParamAttributes.push_back(
|
||||
ExternalAttribute{CurrValue, ExternalAttrs});
|
||||
|
@ -796,18 +669,18 @@ CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) {
|
|||
// Special handling for globals and arguments
|
||||
for (auto *External : GraphBuilder.getExternalValues()) {
|
||||
SetBuilder.add(External);
|
||||
auto Attr = valueToAttr(External);
|
||||
if (Attr.hasValue()) {
|
||||
SetBuilder.noteAttributes(External, *Attr);
|
||||
if (*Attr == AttrGlobal)
|
||||
SetBuilder.addAttributesBelow(External, 1, AttrUnknown);
|
||||
auto Attr = getGlobalOrArgAttrFromValue(*External);
|
||||
if (Attr.any()) {
|
||||
SetBuilder.noteAttributes(External, Attr);
|
||||
if (isa<GlobalValue>(External))
|
||||
SetBuilder.addAttributesBelow(External, 1, getAttrUnknown());
|
||||
else
|
||||
SetBuilder.addAttributesBelow(External, 1, AttrCaller);
|
||||
SetBuilder.addAttributesBelow(External, 1, getAttrCaller());
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for interprocedural aliases
|
||||
for (auto &Edge : GraphBuilder.getInterprocEdges()) {
|
||||
for (auto &Edge : GraphBuilder.getInstantiatedRelations()) {
|
||||
auto FromVal = Edge.From.Val;
|
||||
auto ToVal = Edge.To.Val;
|
||||
SetBuilder.add(FromVal);
|
||||
|
@ -817,17 +690,17 @@ CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) {
|
|||
}
|
||||
|
||||
// Special handling for interprocedural attributes
|
||||
for (auto &IPAttr : GraphBuilder.getInterprocAttrs()) {
|
||||
auto Val = IPAttr.Node.Val;
|
||||
for (auto &IPAttr : GraphBuilder.getInstantiatedAttrs()) {
|
||||
auto Val = IPAttr.IValue.Val;
|
||||
SetBuilder.add(Val);
|
||||
SetBuilder.addAttributesBelow(Val, IPAttr.Node.DerefLevel, IPAttr.Attr);
|
||||
SetBuilder.addAttributesBelow(Val, IPAttr.IValue.DerefLevel, IPAttr.Attr);
|
||||
}
|
||||
|
||||
// Special handling for opaque external functions
|
||||
for (auto *Escape : GraphBuilder.getEscapedValues()) {
|
||||
SetBuilder.add(Escape);
|
||||
SetBuilder.noteAttributes(Escape, AttrEscaped);
|
||||
SetBuilder.addAttributesBelow(Escape, 1, AttrUnknown);
|
||||
SetBuilder.noteAttributes(Escape, getAttrEscaped());
|
||||
SetBuilder.addAttributesBelow(Escape, 1, getAttrUnknown());
|
||||
}
|
||||
|
||||
return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
|
||||
|
@ -923,7 +796,7 @@ AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA,
|
|||
return MayAlias;
|
||||
if (AttrsA.none() || AttrsB.none())
|
||||
return NoAlias;
|
||||
if (isUnknownAttr(AttrsA) || isUnknownAttr(AttrsB))
|
||||
if (hasUnknownOrCallerAttr(AttrsA) || hasUnknownOrCallerAttr(AttrsB))
|
||||
return MayAlias;
|
||||
if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB))
|
||||
return MayAlias;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
add_llvm_library(LLVMAnalysis
|
||||
AliasAnalysis.cpp
|
||||
AliasAnalysisEvaluator.cpp
|
||||
AliasAnalysisSummary.cpp
|
||||
AliasSetTracker.cpp
|
||||
Analysis.cpp
|
||||
AssumptionCache.cpp
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef LLVM_ADT_STRATIFIEDSETS_H
|
||||
#define LLVM_ADT_STRATIFIEDSETS_H
|
||||
|
||||
#include "AliasAnalysisSummary.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
|
@ -34,17 +35,6 @@ struct StratifiedInfo {
|
|||
/// For field sensitivity, etc. we can tack fields on here.
|
||||
};
|
||||
|
||||
/// The number of attributes that StratifiedAttrs should contain. Attributes are
|
||||
/// described below, and 32 was an arbitrary choice because it fits nicely in 32
|
||||
/// bits (because we use a bitset for StratifiedAttrs).
|
||||
static const unsigned NumStratifiedAttrs = 32;
|
||||
|
||||
/// These are attributes that the users of StratifiedSets/StratifiedSetBuilders
|
||||
/// may use for various purposes. These also have the special property of that
|
||||
/// they are merged down. So, if set A is above set B, and one decides to set an
|
||||
/// attribute in set A, then the attribute will automatically be set in set B.
|
||||
typedef std::bitset<NumStratifiedAttrs> StratifiedAttrs;
|
||||
|
||||
/// A "link" between two StratifiedSets.
|
||||
struct StratifiedLink {
|
||||
/// \brief This is a value used to signify "does not exist" where the
|
||||
|
@ -62,7 +52,7 @@ struct StratifiedLink {
|
|||
StratifiedIndex Below;
|
||||
|
||||
/// Attributes for these StratifiedSets.
|
||||
StratifiedAttrs Attrs;
|
||||
AliasAttrs Attrs;
|
||||
|
||||
StratifiedLink() : Above(SetSentinel), Below(SetSentinel) {}
|
||||
|
||||
|
@ -243,14 +233,14 @@ template <typename T> class StratifiedSetsBuilder {
|
|||
return Link.Above;
|
||||
}
|
||||
|
||||
StratifiedAttrs &getAttrs() {
|
||||
AliasAttrs getAttrs() {
|
||||
assert(!isRemapped());
|
||||
return Link.Attrs;
|
||||
}
|
||||
|
||||
void setAttrs(const StratifiedAttrs &other) {
|
||||
void setAttrs(AliasAttrs Other) {
|
||||
assert(!isRemapped());
|
||||
Link.Attrs |= other;
|
||||
Link.Attrs |= Other;
|
||||
}
|
||||
|
||||
bool isRemapped() const { return Remap != StratifiedLink::SetSentinel; }
|
||||
|
@ -396,9 +386,9 @@ public:
|
|||
return addAtMerging(ToAdd, Below);
|
||||
}
|
||||
|
||||
/// \brief Set the StratifiedAttrs of the set "Level"-levels below "Main". If
|
||||
/// \brief Set the AliasAttrs of the set "Level"-levels below "Main". If
|
||||
/// there is no set below "Main", create one for it.
|
||||
void addAttributesBelow(const T &Main, unsigned Level, StratifiedAttrs Attr) {
|
||||
void addAttributesBelow(const T &Main, unsigned Level, AliasAttrs Attr) {
|
||||
assert(has(Main));
|
||||
auto Index = *indexOf(Main);
|
||||
auto *Link = &linksAt(Index);
|
||||
|
@ -436,7 +426,7 @@ public:
|
|||
merge(MainIndex, ToAddIndex);
|
||||
}
|
||||
|
||||
void noteAttributes(const T &Main, const StratifiedAttrs &NewAttrs) {
|
||||
void noteAttributes(const T &Main, AliasAttrs NewAttrs) {
|
||||
assert(has(Main));
|
||||
auto *Info = *get(Main);
|
||||
auto &Link = linksAt(Info->Index);
|
||||
|
@ -538,7 +528,7 @@ private:
|
|||
// match `LinksFrom.Below`
|
||||
// > If both have links above, deal with those next.
|
||||
while (LinksInto->hasBelow() && LinksFrom->hasBelow()) {
|
||||
auto &FromAttrs = LinksFrom->getAttrs();
|
||||
auto FromAttrs = LinksFrom->getAttrs();
|
||||
LinksInto->setAttrs(FromAttrs);
|
||||
|
||||
// Remap needs to happen after getBelow(), but before
|
||||
|
|
Loading…
Reference in New Issue