412 changes: 409 additions & 3 deletions llvm/lib/Analysis/CFLAndersAliasAnalysis.cpp

Large diffs are not rendered by default.

51 changes: 31 additions & 20 deletions llvm/lib/Analysis/CFLGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class CFLGraph {
typedef std::vector<Edge> EdgeList;

struct NodeInfo {
EdgeList Edges;
EdgeList Edges, ReverseEdges;
AliasAttrs Attr;
};

Expand Down Expand Up @@ -77,12 +77,6 @@ class CFLGraph {
typedef DenseMap<Value *, ValueInfo> ValueMap;
ValueMap ValueImpls;

const NodeInfo *getNode(Node N) const {
auto Itr = ValueImpls.find(N.Val);
if (Itr == ValueImpls.end() || Itr->second.getNumLevels() <= N.DerefLevel)
return nullptr;
return &Itr->second.getNodeInfoAtLevel(N.DerefLevel);
}
NodeInfo *getNode(Node N) {
auto Itr = ValueImpls.find(N.Val);
if (Itr == ValueImpls.end() || Itr->second.getNumLevels() <= N.DerefLevel)
Expand All @@ -108,11 +102,20 @@ class CFLGraph {
}

void addEdge(Node From, Node To, int64_t Offset = 0) {
assert(getNode(To) != nullptr);

auto *FromInfo = getNode(From);
assert(FromInfo != nullptr);
auto *ToInfo = getNode(To);
assert(ToInfo != nullptr);

FromInfo->Edges.push_back(Edge{To});
ToInfo->ReverseEdges.push_back(Edge{From});
}

const NodeInfo *getNode(Node N) const {
auto Itr = ValueImpls.find(N.Val);
if (Itr == ValueImpls.end() || Itr->second.getNumLevels() <= N.DerefLevel)
return nullptr;
return &Itr->second.getNodeInfoAtLevel(N.DerefLevel);
}

AliasAttrs attrFor(Node N) const {
Expand Down Expand Up @@ -203,16 +206,24 @@ template <typename CFLAA> class CFLGraphBuilder {
}
}

void addDerefEdge(Value *From, Value *To) {
void addDerefEdge(Value *From, Value *To, bool IsRead) {
assert(From != nullptr && To != nullptr);
if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
return;
addNode(From);
addNode(To);
Graph.addNode(InstantiatedValue{From, 1});
Graph.addEdge(InstantiatedValue{From, 1}, InstantiatedValue{To, 0});
if (IsRead) {
Graph.addNode(InstantiatedValue{From, 1});
Graph.addEdge(InstantiatedValue{From, 1}, InstantiatedValue{To, 0});
} else {
Graph.addNode(InstantiatedValue{To, 1});
Graph.addEdge(InstantiatedValue{From, 0}, InstantiatedValue{To, 1});
}
}

void addLoadEdge(Value *From, Value *To) { addDerefEdge(From, To, true); }
void addStoreEdge(Value *From, Value *To) { addDerefEdge(From, To, false); }

public:
GetEdgesVisitor(CFLGraphBuilder &Builder)
: AA(Builder.Analysis), TLI(Builder.TLI), Graph(Builder.Graph),
Expand Down Expand Up @@ -256,13 +267,13 @@ template <typename CFLAA> class CFLGraphBuilder {
void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) {
auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getNewValOperand();
addDerefEdge(Ptr, Val);
addStoreEdge(Val, Ptr);
}

void visitAtomicRMWInst(AtomicRMWInst &Inst) {
auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getValOperand();
addDerefEdge(Ptr, Val);
addStoreEdge(Val, Ptr);
}

void visitPHINode(PHINode &Inst) {
Expand Down Expand Up @@ -292,13 +303,13 @@ template <typename CFLAA> class CFLGraphBuilder {
void visitLoadInst(LoadInst &Inst) {
auto *Ptr = Inst.getPointerOperand();
auto *Val = &Inst;
addDerefEdge(Ptr, Val);
addLoadEdge(Ptr, Val);
}

void visitStoreInst(StoreInst &Inst) {
auto *Ptr = Inst.getPointerOperand();
auto *Val = Inst.getValueOperand();
addDerefEdge(Ptr, Val);
addStoreEdge(Val, Ptr);
}

void visitVAArgInst(VAArgInst &Inst) {
Expand Down Expand Up @@ -419,14 +430,14 @@ template <typename CFLAA> class CFLGraphBuilder {
void visitExtractElementInst(ExtractElementInst &Inst) {
auto *Ptr = Inst.getVectorOperand();
auto *Val = &Inst;
addDerefEdge(Ptr, Val);
addLoadEdge(Ptr, Val);
}

void visitInsertElementInst(InsertElementInst &Inst) {
auto *Vec = Inst.getOperand(0);
auto *Val = Inst.getOperand(1);
addAssignEdge(Vec, &Inst);
addDerefEdge(&Inst, Val);
addStoreEdge(Val, &Inst);
}

void visitLandingPadInst(LandingPadInst &Inst) {
Expand All @@ -440,12 +451,12 @@ template <typename CFLAA> class CFLGraphBuilder {
auto *Agg = Inst.getOperand(0);
auto *Val = Inst.getOperand(1);
addAssignEdge(Agg, &Inst);
addDerefEdge(&Inst, Val);
addStoreEdge(Val, &Inst);
}

void visitExtractValueInst(ExtractValueInst &Inst) {
auto *Ptr = Inst.getAggregateOperand();
addDerefEdge(Ptr, &Inst);
addLoadEdge(Ptr, &Inst);
}

void visitShuffleVectorInst(ShuffleVectorInst &Inst) {
Expand Down
24 changes: 24 additions & 0 deletions llvm/test/Analysis/CFLAliasAnalysis/Andersen/assign.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; This testcase ensures that CFL AA handles assignment in an inclusion-based
; manner

; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s

; CHECK-LABEL: Function: test_assign
; CHECK: NoAlias: i64* %a, i64* %b
; CHECK: NoAlias: i32* %c, i64* %b
; CHECK: NoAlias: i32* %d, i64* %a
; CHECK: NoAlias: i32* %c, i32* %d
; CHECK: MayAlias: i32* %e, i64* %a
; CHECK: MayAlias: i32* %e, i64* %b
; CHECK: MayAlias: i32* %c, i32* %e
; CHECK: MayAlias: i32* %d, i32* %e
define void @test_assign(i1 %cond) {
%a = alloca i64, align 8
%b = alloca i64, align 8

%c = bitcast i64* %a to i32*
%d = bitcast i64* %b to i32*
%e = select i1 %cond, i32* %c, i32* %d
ret void
}
23 changes: 23 additions & 0 deletions llvm/test/Analysis/CFLAliasAnalysis/Andersen/assign2.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
; This testcase ensures that CFL AA handles assignment in an inclusion-based
; manner

; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s

; CHECK-LABEL: Function: test_assign2
; CHECK: NoAlias: i32* %b, i64* %a
; CHECK: NoAlias: i32* %b, i32* %c
; CHECK: NoAlias: i32* %b, i32* %d
; CHECK: MayAlias: i32* %e, i64* %a
; CHECK: MayAlias: i32* %b, i32* %e
; CHECK: MayAlias: i32* %c, i32* %e
; CHECK: MayAlias: i32* %d, i32* %e
define void @test_assign2(i1 %cond) {
%a = alloca i64, align 8
%b = alloca i32, align 4

%c = bitcast i64* %a to i32*
%d = bitcast i64* %a to i32*
%e = select i1 %cond, i32* %c, i32* %b
ret void
}
34 changes: 34 additions & 0 deletions llvm/test/Analysis/CFLAliasAnalysis/Andersen/cycle.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; This testcase ensures that CFL AA handles assignment cycles correctly

; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s

; CHECK-LABEL: Function: test_cycle
; CHECK: NoAlias: i64* %a, i64** %b
; CHECK: NoAlias: i64* %a, i64*** %c
; CHECK: NoAlias: i64** %b, i64*** %c
; CHECK: NoAlias: i64* %a, i64**** %d
; CHECK: NoAlias: i64** %b, i64**** %d
; CHECK: NoAlias: i64*** %c, i64**** %d
; CHECK: NoAlias: i64* %a, i64* %e
; CHECK: NoAlias: i64* %e, i64** %b
; CHECK: NoAlias: i64* %e, i64*** %c
; CHECK: MayAlias: i64* %a, i64* %f
; CHECK: NoAlias: i64* %f, i64** %b
; CHECK: NoAlias: i64* %f, i64*** %c
; CHECK: MayAlias: i64* %f, i64**** %d
; CHECK: MayAlias: i64* %e, i64* %f
define void @test_cycle() {
%a = alloca i64, align 8
%b = alloca i64*, align 8
%c = alloca i64**, align 8
%d = alloca i64***, align 8
store i64* %a, i64** %b
store i64** %b, i64*** %c
store i64*** %c, i64**** %d

%e = bitcast i64**** %d to i64*
store i64* %e, i64** %b
%f = load i64*, i64** %b
ret void
}
21 changes: 21 additions & 0 deletions llvm/test/Analysis/CFLAliasAnalysis/Andersen/memalias.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
; This testcase ensures that CFL AA correctly handles simple memory alias
; pattern

; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s

; CHECK-LABEL: Function: test_memalias
; CHECK: NoAlias: i64* %a, i64** %b
; CHECK: NoAlias: i32** %c, i64* %a
; CHECK: MayAlias: i32* %d, i64* %a
; CHECK: NoAlias: i32* %d, i64** %b
; CHECK: NoAlias: i32* %d, i32** %c
define void @test_memalias() {
%a = alloca i64, align 8
%b = alloca i64*, align 8
store i64* %a, i64** %b

%c = bitcast i64** %b to i32**
%d = load i32*, i32** %c
ret void
}