forked from OSchip/llvm-project
[CFLAA] Split the CFL graph out from CFLSteens. NFC.
Patch by Jia Chen. Differential Revision: http://reviews.llvm.org/D21963 llvm-svn: 274591
This commit is contained in:
parent
a362b09a81
commit
1ca8affb24
|
@ -25,9 +25,11 @@
|
|||
// FunctionPasses to run concurrently.
|
||||
|
||||
#include "llvm/Analysis/CFLAndersAliasAnalysis.h"
|
||||
#include "CFLGraph.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::cflaa;
|
||||
|
||||
#define DEBUG_TYPE "cfl-anders-aa"
|
||||
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
//======- CFLGraph.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 CFLGraph, an auxiliary data structure used by CFL-based
|
||||
/// alias analysis.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CFLGRAPH_H
|
||||
#define LLVM_ANALYSIS_CFLGRAPH_H
|
||||
|
||||
#include "StratifiedSets.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 {
|
||||
/// The weight assigned when assigning from or to a value. For example, in:
|
||||
/// %b = getelementptr %a, 0
|
||||
/// ...The relationships are %b assign %a, and %a assign %b. This used to be
|
||||
/// two edges, but having a distinction bought us nothing.
|
||||
Assign,
|
||||
|
||||
/// The edge used when we have an edge going from some handle to a Value.
|
||||
/// Examples of this include:
|
||||
/// %b = load %a (%b Dereference %a)
|
||||
/// %b = extractelement %a, 0 (%a Dereference %b)
|
||||
Dereference,
|
||||
|
||||
/// The edge used when our edge goes from a value to a handle that may have
|
||||
/// contained it at some point. Examples:
|
||||
/// %b = load %a (%a Reference %b)
|
||||
/// %b = extractelement %a, 0 (%b Reference %a)
|
||||
Reference
|
||||
};
|
||||
|
||||
/// \brief The Program Expression Graph (PEG) of CFL analysis
|
||||
/// CFLGraph is auxiliary data structure used by CFL-based alias analysis to
|
||||
/// describe flow-insensitive pointer-related behaviors. Given an LLVM function,
|
||||
/// the main purpose of this graph is to abstract away unrelated facts and
|
||||
/// translate the rest into a form that can be easily digested by CFL analyses.
|
||||
class CFLGraph {
|
||||
typedef Value *Node;
|
||||
|
||||
struct Edge {
|
||||
EdgeType Type;
|
||||
Node Other;
|
||||
};
|
||||
|
||||
typedef std::vector<Edge> EdgeList;
|
||||
|
||||
struct NodeInfo {
|
||||
EdgeList Edges;
|
||||
StratifiedAttrs Attr;
|
||||
};
|
||||
|
||||
typedef DenseMap<Node, NodeInfo> NodeMap;
|
||||
NodeMap NodeImpls;
|
||||
|
||||
// Gets the inverse of a given EdgeType.
|
||||
static EdgeType flipWeight(EdgeType Initial) {
|
||||
switch (Initial) {
|
||||
case EdgeType::Assign:
|
||||
return EdgeType::Assign;
|
||||
case EdgeType::Dereference:
|
||||
return EdgeType::Reference;
|
||||
case EdgeType::Reference:
|
||||
return EdgeType::Dereference;
|
||||
}
|
||||
llvm_unreachable("Incomplete coverage of EdgeType enum");
|
||||
}
|
||||
|
||||
const NodeInfo *getNode(Node N) const {
|
||||
auto Itr = NodeImpls.find(N);
|
||||
if (Itr == NodeImpls.end())
|
||||
return nullptr;
|
||||
return &Itr->second;
|
||||
}
|
||||
NodeInfo *getNode(Node N) {
|
||||
auto Itr = NodeImpls.find(N);
|
||||
if (Itr == NodeImpls.end())
|
||||
return nullptr;
|
||||
return &Itr->second;
|
||||
}
|
||||
|
||||
static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
|
||||
typedef std::pointer_to_unary_function<const NodeMap::value_type &, Node>
|
||||
NodeDerefFun;
|
||||
|
||||
public:
|
||||
typedef EdgeList::const_iterator const_edge_iterator;
|
||||
typedef mapped_iterator<NodeMap::const_iterator, NodeDerefFun>
|
||||
const_node_iterator;
|
||||
|
||||
bool addNode(Node N) {
|
||||
return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), 0})).second;
|
||||
}
|
||||
|
||||
void addAttr(Node N, StratifiedAttrs Attr) {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
Info->Attr |= Attr;
|
||||
}
|
||||
|
||||
void addEdge(Node From, Node To, EdgeType Type) {
|
||||
auto *FromInfo = getNode(From);
|
||||
assert(FromInfo != nullptr);
|
||||
auto *ToInfo = getNode(To);
|
||||
assert(ToInfo != nullptr);
|
||||
|
||||
FromInfo->Edges.push_back(Edge{Type, To});
|
||||
ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
|
||||
}
|
||||
|
||||
StratifiedAttrs attrFor(Node N) const {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
return Info->Attr;
|
||||
}
|
||||
|
||||
iterator_range<const_edge_iterator> edgesFor(Node N) const {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
auto &Edges = Info->Edges;
|
||||
return make_range(Edges.begin(), Edges.end());
|
||||
}
|
||||
|
||||
iterator_range<const_node_iterator> nodes() const {
|
||||
return make_range<const_node_iterator>(
|
||||
map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
|
||||
map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
|
||||
}
|
||||
|
||||
bool empty() const { return NodeImpls.empty(); }
|
||||
std::size_t size() const { return NodeImpls.size(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -36,7 +36,7 @@
|
|||
// FunctionPasses to run concurrently.
|
||||
|
||||
#include "llvm/Analysis/CFLSteensAliasAnalysis.h"
|
||||
#include "StratifiedSets.h"
|
||||
#include "CFLGraph.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
|
@ -57,6 +57,7 @@
|
|||
#include <tuple>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::cflaa;
|
||||
|
||||
#define DEBUG_TYPE "cfl-steens-aa"
|
||||
|
||||
|
@ -148,7 +149,6 @@ LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
|
|||
// ctor for some versions of MSVC that we support. We could maybe refactor,
|
||||
// but...
|
||||
using StratifiedAttr = unsigned;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrNone = 0;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrEscaped = 1 << AttrEscapedIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex;
|
||||
LLVM_CONSTEXPR StratifiedAttr AttrGlobal = 1 << AttrGlobalIndex;
|
||||
|
@ -163,126 +163,6 @@ LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
|
|||
/// represent that locally.
|
||||
enum class Level { Same, Above, Below };
|
||||
|
||||
/// Edges can be one of four "weights" -- each weight must have an inverse
|
||||
/// weight (Assign has Assign; Reference has Dereference).
|
||||
enum class EdgeType {
|
||||
/// The weight assigned when assigning from or to a value. For example, in:
|
||||
/// %b = getelementptr %a, 0
|
||||
/// ...The relationships are %b assign %a, and %a assign %b. This used to be
|
||||
/// two edges, but having a distinction bought us nothing.
|
||||
Assign,
|
||||
|
||||
/// The edge used when we have an edge going from some handle to a Value.
|
||||
/// Examples of this include:
|
||||
/// %b = load %a (%b Dereference %a)
|
||||
/// %b = extractelement %a, 0 (%a Dereference %b)
|
||||
Dereference,
|
||||
|
||||
/// The edge used when our edge goes from a value to a handle that may have
|
||||
/// contained it at some point. Examples:
|
||||
/// %b = load %a (%a Reference %b)
|
||||
/// %b = extractelement %a, 0 (%b Reference %a)
|
||||
Reference
|
||||
};
|
||||
|
||||
/// The Program Expression Graph (PEG) of CFL analysis
|
||||
class CFLGraph {
|
||||
typedef Value *Node;
|
||||
|
||||
struct Edge {
|
||||
EdgeType Type;
|
||||
Node Other;
|
||||
};
|
||||
|
||||
typedef std::vector<Edge> EdgeList;
|
||||
|
||||
struct NodeInfo {
|
||||
EdgeList Edges;
|
||||
StratifiedAttrs Attr;
|
||||
};
|
||||
|
||||
typedef DenseMap<Node, NodeInfo> NodeMap;
|
||||
NodeMap NodeImpls;
|
||||
|
||||
// Gets the inverse of a given EdgeType.
|
||||
static EdgeType flipWeight(EdgeType Initial) {
|
||||
switch (Initial) {
|
||||
case EdgeType::Assign:
|
||||
return EdgeType::Assign;
|
||||
case EdgeType::Dereference:
|
||||
return EdgeType::Reference;
|
||||
case EdgeType::Reference:
|
||||
return EdgeType::Dereference;
|
||||
}
|
||||
llvm_unreachable("Incomplete coverage of EdgeType enum");
|
||||
}
|
||||
|
||||
const NodeInfo *getNode(Node N) const {
|
||||
auto Itr = NodeImpls.find(N);
|
||||
if (Itr == NodeImpls.end())
|
||||
return nullptr;
|
||||
return &Itr->second;
|
||||
}
|
||||
NodeInfo *getNode(Node N) {
|
||||
auto Itr = NodeImpls.find(N);
|
||||
if (Itr == NodeImpls.end())
|
||||
return nullptr;
|
||||
return &Itr->second;
|
||||
}
|
||||
|
||||
static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
|
||||
typedef std::pointer_to_unary_function<const NodeMap::value_type &, Node>
|
||||
NodeDerefFun;
|
||||
|
||||
public:
|
||||
typedef EdgeList::const_iterator const_edge_iterator;
|
||||
typedef mapped_iterator<NodeMap::const_iterator, NodeDerefFun>
|
||||
const_node_iterator;
|
||||
|
||||
bool addNode(Node N) {
|
||||
return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), AttrNone}))
|
||||
.second;
|
||||
}
|
||||
|
||||
void addAttr(Node N, StratifiedAttrs Attr) {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
Info->Attr |= Attr;
|
||||
}
|
||||
|
||||
void addEdge(Node From, Node To, EdgeType Type) {
|
||||
auto *FromInfo = getNode(From);
|
||||
assert(FromInfo != nullptr);
|
||||
auto *ToInfo = getNode(To);
|
||||
assert(ToInfo != nullptr);
|
||||
|
||||
FromInfo->Edges.push_back(Edge{Type, To});
|
||||
ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
|
||||
}
|
||||
|
||||
StratifiedAttrs attrFor(Node N) const {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
return Info->Attr;
|
||||
}
|
||||
|
||||
iterator_range<const_edge_iterator> edgesFor(Node N) const {
|
||||
auto *Info = getNode(N);
|
||||
assert(Info != nullptr);
|
||||
auto &Edges = Info->Edges;
|
||||
return make_range(Edges.begin(), Edges.end());
|
||||
}
|
||||
|
||||
iterator_range<const_node_iterator> nodes() const {
|
||||
return make_range<const_node_iterator>(
|
||||
map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
|
||||
map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
|
||||
}
|
||||
|
||||
bool empty() const { return NodeImpls.empty(); }
|
||||
std::size_t size() const { return NodeImpls.size(); }
|
||||
};
|
||||
|
||||
// This is the result of instantiating InterfaceValue at a particular callsite
|
||||
struct InterprocNode {
|
||||
Value *Val;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace cflaa {
|
||||
/// An index into Stratified Sets.
|
||||
typedef unsigned StratifiedIndex;
|
||||
/// NOTE: ^ This can't be a short -- bootstrapping clang has a case where
|
||||
|
@ -644,4 +645,5 @@ private:
|
|||
bool inbounds(StratifiedIndex N) const { return N < Links.size(); }
|
||||
};
|
||||
}
|
||||
}
|
||||
#endif // LLVM_ADT_STRATIFIEDSETS_H
|
||||
|
|
Loading…
Reference in New Issue