[CFLAA] Ignore non-pointers, move Attrs to graph nodes.

This patch makes CFLAA ignore non-pointer values, since we can now
sanely do that with the escaping/unknown attributes. Additionally,
StratifiedAttrs make more sense to sit on nodes than edges (since
they're properties of values, and ultimately end up on the nodes of
StratifiedSets). So, this patch puts said attributes on nodes.

Patch by Jia Chen.

Differential Revision: http://reviews.llvm.org/D21387

llvm-svn: 272833
This commit is contained in:
George Burgess IV 2016-06-15 20:43:41 +00:00
parent e28e7f234d
commit 259d90194e
1 changed files with 93 additions and 64 deletions

View File

@ -132,13 +132,18 @@ class CFLGraph {
typedef Value *Node; typedef Value *Node;
struct Edge { struct Edge {
StratifiedAttrs Attr;
EdgeType Type; EdgeType Type;
Node Other; Node Other;
}; };
typedef std::vector<Edge> EdgeList; typedef std::vector<Edge> EdgeList;
typedef DenseMap<Node, EdgeList> NodeMap;
struct NodeInfo {
EdgeList Edges;
StratifiedAttrs Attr;
};
typedef DenseMap<Node, NodeInfo> NodeMap;
NodeMap NodeImpls; NodeMap NodeImpls;
// Gets the inverse of a given EdgeType. // Gets the inverse of a given EdgeType.
@ -154,13 +159,13 @@ class CFLGraph {
llvm_unreachable("Incomplete coverage of EdgeType enum"); llvm_unreachable("Incomplete coverage of EdgeType enum");
} }
const EdgeList *getNode(Node N) const { const NodeInfo *getNode(Node N) const {
auto Itr = NodeImpls.find(N); auto Itr = NodeImpls.find(N);
if (Itr == NodeImpls.end()) if (Itr == NodeImpls.end())
return nullptr; return nullptr;
return &Itr->second; return &Itr->second;
} }
EdgeList *getNode(Node N) { NodeInfo *getNode(Node N) {
auto Itr = NodeImpls.find(N); auto Itr = NodeImpls.find(N);
if (Itr == NodeImpls.end()) if (Itr == NodeImpls.end())
return nullptr; return nullptr;
@ -177,24 +182,37 @@ public:
const_node_iterator; const_node_iterator;
bool addNode(Node N) { bool addNode(Node N) {
return NodeImpls.insert(std::make_pair(N, EdgeList())).second; return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), AttrNone}))
.second;
} }
void addEdge(Node From, Node To, EdgeType Type, void addAttr(Node N, StratifiedAttrs Attr) {
StratifiedAttrs Attr = StratifiedAttrs()) { auto *Info = getNode(N);
auto FromEdges = getNode(From); assert(Info != nullptr);
assert(FromEdges != nullptr); Info->Attr |= Attr;
auto ToEdges = getNode(To); }
assert(ToEdges != nullptr);
FromEdges->push_back(Edge{Attr, Type, To}); void addEdge(Node From, Node To, EdgeType Type) {
ToEdges->push_back(Edge{Attr, flipWeight(Type), From}); 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 { iterator_range<const_edge_iterator> edgesFor(Node N) const {
auto Edges = getNode(N); auto *Info = getNode(N);
assert(Edges != nullptr); assert(Info != nullptr);
return make_range(Edges->begin(), Edges->end()); auto &Edges = Info->Edges;
return make_range(Edges.begin(), Edges.end());
} }
iterator_range<const_node_iterator> nodes() const { iterator_range<const_node_iterator> nodes() const {
@ -234,11 +252,18 @@ class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
visitConstantExpr(CExpr); visitConstantExpr(CExpr);
} }
void addEdge(Value *From, Value *To, EdgeType Type, StratifiedAttrs Attr) { void addNodeWithAttr(Value *Val, StratifiedAttrs Attr) {
addNode(Val);
Graph.addAttr(Val, Attr);
}
void addEdge(Value *From, Value *To, EdgeType Type) {
if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
return;
addNode(From); addNode(From);
if (To != From) if (To != From)
addNode(To); addNode(To);
Graph.addEdge(From, To, Type, Attr); Graph.addEdge(From, To, Type);
} }
public: public:
@ -254,46 +279,46 @@ public:
void visitPtrToIntInst(PtrToIntInst &Inst) { void visitPtrToIntInst(PtrToIntInst &Inst) {
auto *Ptr = Inst.getOperand(0); auto *Ptr = Inst.getOperand(0);
addEdge(Ptr, &Inst, EdgeType::Assign, AttrEscaped); addNodeWithAttr(Ptr, AttrEscaped);
} }
void visitIntToPtrInst(IntToPtrInst &Inst) { void visitIntToPtrInst(IntToPtrInst &Inst) {
auto *Ptr = &Inst; auto *Ptr = &Inst;
addEdge(Ptr, Ptr, EdgeType::Assign, AttrUnknown); addNodeWithAttr(Ptr, AttrUnknown);
} }
void visitCastInst(CastInst &Inst) { void visitCastInst(CastInst &Inst) {
auto *Src = Inst.getOperand(0); auto *Src = Inst.getOperand(0);
addEdge(Src, &Inst, EdgeType::Assign, AttrNone); addEdge(Src, &Inst, EdgeType::Assign);
} }
void visitBinaryOperator(BinaryOperator &Inst) { void visitBinaryOperator(BinaryOperator &Inst) {
auto *Op1 = Inst.getOperand(0); auto *Op1 = Inst.getOperand(0);
auto *Op2 = Inst.getOperand(1); auto *Op2 = Inst.getOperand(1);
addEdge(Op1, &Inst, EdgeType::Assign, AttrNone); addEdge(Op1, &Inst, EdgeType::Assign);
addEdge(Op2, &Inst, EdgeType::Assign, AttrNone); addEdge(Op2, &Inst, EdgeType::Assign);
} }
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) { void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) {
auto *Ptr = Inst.getPointerOperand(); auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getNewValOperand(); auto *Val = Inst.getNewValOperand();
addEdge(Ptr, Val, EdgeType::Dereference, AttrNone); addEdge(Ptr, Val, EdgeType::Dereference);
} }
void visitAtomicRMWInst(AtomicRMWInst &Inst) { void visitAtomicRMWInst(AtomicRMWInst &Inst) {
auto *Ptr = Inst.getPointerOperand(); auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getValOperand(); auto *Val = Inst.getValOperand();
addEdge(Ptr, Val, EdgeType::Dereference, AttrNone); addEdge(Ptr, Val, EdgeType::Dereference);
} }
void visitPHINode(PHINode &Inst) { void visitPHINode(PHINode &Inst) {
for (Value *Val : Inst.incoming_values()) for (Value *Val : Inst.incoming_values())
addEdge(Val, &Inst, EdgeType::Assign, AttrNone); addEdge(Val, &Inst, EdgeType::Assign);
} }
void visitGetElementPtrInst(GetElementPtrInst &Inst) { void visitGetElementPtrInst(GetElementPtrInst &Inst) {
auto *Op = Inst.getPointerOperand(); auto *Op = Inst.getPointerOperand();
addEdge(Op, &Inst, EdgeType::Assign, AttrNone); addEdge(Op, &Inst, EdgeType::Assign);
} }
void visitSelectInst(SelectInst &Inst) { void visitSelectInst(SelectInst &Inst) {
@ -304,8 +329,8 @@ public:
auto *TrueVal = Inst.getTrueValue(); auto *TrueVal = Inst.getTrueValue();
auto *FalseVal = Inst.getFalseValue(); auto *FalseVal = Inst.getFalseValue();
addEdge(TrueVal, &Inst, EdgeType::Assign, AttrNone); addEdge(TrueVal, &Inst, EdgeType::Assign);
addEdge(FalseVal, &Inst, EdgeType::Assign, AttrNone); addEdge(FalseVal, &Inst, EdgeType::Assign);
} }
void visitAllocaInst(AllocaInst &Inst) { Graph.addNode(&Inst); } void visitAllocaInst(AllocaInst &Inst) { Graph.addNode(&Inst); }
@ -313,13 +338,13 @@ public:
void visitLoadInst(LoadInst &Inst) { void visitLoadInst(LoadInst &Inst) {
auto *Ptr = Inst.getPointerOperand(); auto *Ptr = Inst.getPointerOperand();
auto *Val = &Inst; auto *Val = &Inst;
addEdge(Val, Ptr, EdgeType::Reference, AttrNone); addEdge(Val, Ptr, EdgeType::Reference);
} }
void visitStoreInst(StoreInst &Inst) { void visitStoreInst(StoreInst &Inst) {
auto *Ptr = Inst.getPointerOperand(); auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getValueOperand(); auto *Val = Inst.getValueOperand();
addEdge(Ptr, Val, EdgeType::Dereference, AttrNone); addEdge(Ptr, Val, EdgeType::Dereference);
} }
void visitVAArgInst(VAArgInst &Inst) { void visitVAArgInst(VAArgInst &Inst) {
@ -329,8 +354,7 @@ public:
// 2. Increments (stores to) *Ptr by some target-specific amount. // 2. Increments (stores to) *Ptr by some target-specific amount.
// For now, we'll handle this like a landingpad instruction (by placing the // For now, we'll handle this like a landingpad instruction (by placing the
// result in its own group, and having that group alias externals). // result in its own group, and having that group alias externals).
auto *Val = &Inst; addNodeWithAttr(&Inst, AttrUnknown);
addEdge(Val, Val, EdgeType::Assign, AttrUnknown);
} }
static bool isFunctionExternal(Function *Fn) { static bool isFunctionExternal(Function *Fn) {
@ -374,9 +398,8 @@ public:
EdgeType Weight; EdgeType Weight;
// Whether we aliased any external values along the way that may be // Whether we aliased any external values along the way that may be
// invisible to the analysis (i.e. landingpad for exceptions, calls for // invisible to the analysis
// interprocedural analysis, etc.) StratifiedAttrs FromAttrs, ToAttrs;
StratifiedAttrs AdditionalAttrs;
}; };
bool bool
@ -424,25 +447,23 @@ public:
auto &ParamInfo = Parameters[I]; auto &ParamInfo = Parameters[I];
auto &ArgVal = Arguments[I]; auto &ArgVal = Arguments[I];
bool AddEdge = false; bool AddEdge = false;
StratifiedAttrs Externals; StratifiedAttrs RetAttrs, ParamAttrs;
for (unsigned X = 0, XE = RetVals.size(); X != XE; ++X) { for (unsigned X = 0, XE = RetVals.size(); X != XE; ++X) {
auto MaybeInfo = Sets.find(RetVals[X]); auto MaybeInfo = Sets.find(RetVals[X]);
if (!MaybeInfo.hasValue()) if (!MaybeInfo.hasValue())
return false; return false;
auto &RetInfo = *MaybeInfo; auto &RetInfo = *MaybeInfo;
auto RetAttrs = Sets.getLink(RetInfo.Index).Attrs; RetAttrs |= Sets.getLink(RetInfo.Index).Attrs;
auto ParamAttrs = Sets.getLink(ParamInfo.Index).Attrs; ParamAttrs |= Sets.getLink(ParamInfo.Index).Attrs;
auto MaybeRelation = auto MaybeRelation =
getIndexRelation(Sets, ParamInfo.Index, RetInfo.Index); getIndexRelation(Sets, ParamInfo.Index, RetInfo.Index);
if (MaybeRelation.hasValue()) { if (MaybeRelation.hasValue())
AddEdge = true; AddEdge = true;
Externals |= RetAttrs | ParamAttrs;
}
} }
if (AddEdge) if (AddEdge)
Output.push_back( Output.push_back(
Edge{FuncValue, ArgVal, EdgeType::Assign, Externals}); Edge{FuncValue, ArgVal, EdgeType::Assign, RetAttrs, ParamAttrs});
} }
if (Parameters.size() != Arguments.size()) if (Parameters.size() != Arguments.size())
@ -468,15 +489,18 @@ public:
if (!MaybeRelation.hasValue()) if (!MaybeRelation.hasValue())
continue; continue;
auto NewAttrs = SubAttrs | MainAttrs; Output.push_back(
Output.push_back(Edge{MainVal, SubVal, EdgeType::Assign, NewAttrs}); Edge{MainVal, SubVal, EdgeType::Assign, MainAttrs, SubAttrs});
} }
} }
} }
// Commit all edges in Output to CFLGraph // Commit all edges in Output to CFLGraph
for (const auto &Edge : Output) for (const auto &Edge : Output) {
addEdge(Edge.From, Edge.To, Edge.Weight, Edge.AdditionalAttrs); addEdge(Edge.From, Edge.To, Edge.Weight);
Graph.addAttr(Edge.From, Edge.FromAttrs);
Graph.addAttr(Edge.To, Edge.ToAttrs);
}
return true; return true;
} }
@ -511,13 +535,14 @@ public:
// anything, too (unless the result is marked noalias). // anything, too (unless the result is marked noalias).
if (!CS.onlyReadsMemory()) if (!CS.onlyReadsMemory())
for (Value *V : CS.args()) { for (Value *V : CS.args()) {
Escapes.insert(V); if (V->getType()->isPointerTy())
Escapes.insert(V);
} }
if (!Inst->getType()->isVoidTy()) { if (!Inst->getType()->isVoidTy()) {
auto *Fn = CS.getCalledFunction(); auto *Fn = CS.getCalledFunction();
if (Fn == nullptr || !Fn->doesNotAlias(0)) if (Fn == nullptr || !Fn->doesNotAlias(0))
addEdge(Inst, Inst, EdgeType::Assign, AttrUnknown); Graph.addAttr(Inst, AttrUnknown);
} }
} }
@ -528,40 +553,40 @@ public:
void visitExtractElementInst(ExtractElementInst &Inst) { void visitExtractElementInst(ExtractElementInst &Inst) {
auto *Ptr = Inst.getVectorOperand(); auto *Ptr = Inst.getVectorOperand();
auto *Val = &Inst; auto *Val = &Inst;
addEdge(Val, Ptr, EdgeType::Reference, AttrNone); addEdge(Val, Ptr, EdgeType::Reference);
} }
void visitInsertElementInst(InsertElementInst &Inst) { void visitInsertElementInst(InsertElementInst &Inst) {
auto *Vec = Inst.getOperand(0); auto *Vec = Inst.getOperand(0);
auto *Val = Inst.getOperand(1); auto *Val = Inst.getOperand(1);
addEdge(Vec, &Inst, EdgeType::Assign, AttrNone); addEdge(Vec, &Inst, EdgeType::Assign);
addEdge(&Inst, Val, EdgeType::Dereference, AttrNone); addEdge(&Inst, Val, EdgeType::Dereference);
} }
void visitLandingPadInst(LandingPadInst &Inst) { void visitLandingPadInst(LandingPadInst &Inst) {
// Exceptions come from "nowhere", from our analysis' perspective. // Exceptions come from "nowhere", from our analysis' perspective.
// So we place the instruction its own group, noting that said group may // So we place the instruction its own group, noting that said group may
// alias externals // alias externals
addEdge(&Inst, &Inst, EdgeType::Assign, AttrUnknown); addNodeWithAttr(&Inst, AttrUnknown);
} }
void visitInsertValueInst(InsertValueInst &Inst) { void visitInsertValueInst(InsertValueInst &Inst) {
auto *Agg = Inst.getOperand(0); auto *Agg = Inst.getOperand(0);
auto *Val = Inst.getOperand(1); auto *Val = Inst.getOperand(1);
addEdge(Agg, &Inst, EdgeType::Assign, AttrNone); addEdge(Agg, &Inst, EdgeType::Assign);
addEdge(&Inst, Val, EdgeType::Dereference, AttrNone); addEdge(&Inst, Val, EdgeType::Dereference);
} }
void visitExtractValueInst(ExtractValueInst &Inst) { void visitExtractValueInst(ExtractValueInst &Inst) {
auto *Ptr = Inst.getAggregateOperand(); auto *Ptr = Inst.getAggregateOperand();
addEdge(&Inst, Ptr, EdgeType::Reference, AttrNone); addEdge(&Inst, Ptr, EdgeType::Reference);
} }
void visitShuffleVectorInst(ShuffleVectorInst &Inst) { void visitShuffleVectorInst(ShuffleVectorInst &Inst) {
auto *From1 = Inst.getOperand(0); auto *From1 = Inst.getOperand(0);
auto *From2 = Inst.getOperand(1); auto *From2 = Inst.getOperand(1);
addEdge(From1, &Inst, EdgeType::Assign, AttrNone); addEdge(From1, &Inst, EdgeType::Assign);
addEdge(From2, &Inst, EdgeType::Assign, AttrNone); addEdge(From2, &Inst, EdgeType::Assign);
} }
void visitConstantExpr(ConstantExpr *CE) { void visitConstantExpr(ConstantExpr *CE) {
@ -603,8 +628,10 @@ class CFLGraphBuilder {
} }
void addArgumentToGraph(Argument &Arg) { void addArgumentToGraph(Argument &Arg) {
Graph.addNode(&Arg); if (Arg.getType()->isPointerTy()) {
ExternalValues.insert(&Arg); Graph.addNode(&Arg);
ExternalValues.insert(&Arg);
}
} }
// Given an Instruction, this will add it to the graph, along with any // Given an Instruction, this will add it to the graph, along with any
@ -777,6 +804,9 @@ CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
if (canSkipAddingToSets(CurValue)) if (canSkipAddingToSets(CurValue))
continue; continue;
auto Attr = Graph.attrFor(CurValue);
SetBuilder.noteAttributes(CurValue, Attr);
for (const auto &Edge : Graph.edgesFor(CurValue)) { for (const auto &Edge : Graph.edgesFor(CurValue)) {
auto Label = Edge.Type; auto Label = Edge.Type;
auto *OtherValue = Edge.Other; auto *OtherValue = Edge.Other;
@ -797,10 +827,6 @@ CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
break; break;
} }
auto Aliasing = Edge.Attr;
SetBuilder.noteAttributes(CurValue, Aliasing);
SetBuilder.noteAttributes(OtherValue, Aliasing);
if (Added) if (Added)
Worklist.push_back(OtherValue); Worklist.push_back(OtherValue);
} }
@ -861,6 +887,9 @@ AliasResult CFLAAResult::query(const MemoryLocation &LocA,
auto *ValA = const_cast<Value *>(LocA.Ptr); auto *ValA = const_cast<Value *>(LocA.Ptr);
auto *ValB = const_cast<Value *>(LocB.Ptr); auto *ValB = const_cast<Value *>(LocB.Ptr);
if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy())
return NoAlias;
Function *Fn = nullptr; Function *Fn = nullptr;
auto MaybeFnA = parentFunctionOfValue(ValA); auto MaybeFnA = parentFunctionOfValue(ValA);
auto MaybeFnB = parentFunctionOfValue(ValB); auto MaybeFnB = parentFunctionOfValue(ValB);