Support in AAEvaluator to print alias queries of loads/stores with TBAA tags.

Add "evaluate-tbaa" to print alias queries of loads/stores. Alias queries
between pointers do not include TBAA tags.

Add testing case for "placement new". TBAA currently says NoAlias.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177772 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manman Ren 2013-03-22 22:34:41 +00:00
parent 1f9c4407c0
commit a2e3834d16
2 changed files with 176 additions and 0 deletions

View File

@ -44,6 +44,8 @@ static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
static cl::opt<bool> EvalTBAA("evaluate-tbaa", cl::ReallyHidden);
namespace {
class AAEval : public FunctionPass {
unsigned NoAlias, MayAlias, PartialAlias, MustAlias;
@ -123,6 +125,15 @@ PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB,
}
}
static inline void
PrintLoadStoreResults(const char *Msg, bool P, const Value *V1,
const Value *V2, const Module *M) {
if (P) {
errs() << " " << Msg << ": " << *V1
<< " <-> " << *V2 << '\n';
}
}
static inline bool isInterestingPointer(Value *V) {
return V->getType()->isPointerTy()
&& !isa<ConstantPointerNull>(V);
@ -133,6 +144,8 @@ bool AAEval::runOnFunction(Function &F) {
SetVector<Value *> Pointers;
SetVector<CallSite> CallSites;
SetVector<Value *> Loads;
SetVector<Value *> Stores;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
if (I->getType()->isPointerTy()) // Add all pointer arguments.
@ -141,6 +154,10 @@ bool AAEval::runOnFunction(Function &F) {
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
if (I->getType()->isPointerTy()) // Add all pointer instructions.
Pointers.insert(&*I);
if (EvalTBAA && isa<LoadInst>(&*I))
Loads.insert(&*I);
if (EvalTBAA && isa<StoreInst>(&*I))
Stores.insert(&*I);
Instruction &Inst = *I;
if (CallSite CS = cast<Value>(&Inst)) {
Value *Callee = CS.getCalledValue();
@ -197,6 +214,61 @@ bool AAEval::runOnFunction(Function &F) {
}
}
if (EvalTBAA) {
// iterate over all pairs of load, store
for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end();
I1 != E; ++I1) {
for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end();
I2 != E2; ++I2) {
switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)),
AA.getLocation(cast<StoreInst>(*I2)))) {
case AliasAnalysis::NoAlias:
PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
F.getParent());
++NoAlias; break;
case AliasAnalysis::MayAlias:
PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
F.getParent());
++MayAlias; break;
case AliasAnalysis::PartialAlias:
PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
F.getParent());
++PartialAlias; break;
case AliasAnalysis::MustAlias:
PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
F.getParent());
++MustAlias; break;
}
}
}
// iterate over all pairs of store, store
for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
I1 != E; ++I1) {
for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
switch (AA.alias(AA.getLocation(cast<StoreInst>(*I1)),
AA.getLocation(cast<StoreInst>(*I2)))) {
case AliasAnalysis::NoAlias:
PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
F.getParent());
++NoAlias; break;
case AliasAnalysis::MayAlias:
PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
F.getParent());
++MayAlias; break;
case AliasAnalysis::PartialAlias:
PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
F.getParent());
++PartialAlias; break;
case AliasAnalysis::MustAlias:
PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
F.getParent());
++MustAlias; break;
}
}
}
}
// Mod/ref alias analysis: compare all pairs of calls and values
for (SetVector<CallSite>::iterator C = CallSites.begin(),
Ce = CallSites.end(); C != Ce; ++C) {

View File

@ -0,0 +1,104 @@
; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-tbaa -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s
; Generated with "clang -cc1 -disable-llvm-optzns -O1 -emit-llvm"
; #include <new>
; struct Foo { long i; };
; struct Bar { void *p; };
; long foo(int n) {
; Foo *f = new Foo;
; f->i = 1;
; for (int i=0; i<n; ++i) {
; Bar *b = new (f) Bar;
; b->p = 0;
; f = new (f) Foo;
; f->i = i;
; }
; return f->i;
; }
; Basic AA says MayAlias, TBAA says NoAlias
; CHECK: MayAlias: i64* %i5, i8** %p
; CHECK: NoAlias: store i64 %conv, i64* %i5, align 8, !tbaa !4 <-> store i8* null, i8** %p, align 8, !tbaa !3
%struct.Foo = type { i64 }
%struct.Bar = type { i8* }
define i64 @_Z3fooi(i32 %n) #0 {
entry:
%n.addr = alloca i32, align 4
%f = alloca %struct.Foo*, align 8
%i1 = alloca i32, align 4
%b = alloca %struct.Bar*, align 8
store i32 %n, i32* %n.addr, align 4, !tbaa !0
%call = call noalias i8* @_Znwm(i64 8)
%0 = bitcast i8* %call to %struct.Foo*
store %struct.Foo* %0, %struct.Foo** %f, align 8, !tbaa !3
%1 = load %struct.Foo** %f, align 8, !tbaa !3
%i = getelementptr inbounds %struct.Foo* %1, i32 0, i32 0
store i64 1, i64* %i, align 8, !tbaa !4
store i32 0, i32* %i1, align 4, !tbaa !0
br label %for.cond
for.cond:
%2 = load i32* %i1, align 4, !tbaa !0
%3 = load i32* %n.addr, align 4, !tbaa !0
%cmp = icmp slt i32 %2, %3
br i1 %cmp, label %for.body, label %for.end
for.body:
%4 = load %struct.Foo** %f, align 8, !tbaa !3
%5 = bitcast %struct.Foo* %4 to i8*
%new.isnull = icmp eq i8* %5, null
br i1 %new.isnull, label %new.cont, label %new.notnull
new.notnull:
%6 = bitcast i8* %5 to %struct.Bar*
br label %new.cont
new.cont:
%7 = phi %struct.Bar* [ %6, %new.notnull ], [ null, %for.body ]
store %struct.Bar* %7, %struct.Bar** %b, align 8, !tbaa !3
%8 = load %struct.Bar** %b, align 8, !tbaa !3
%p = getelementptr inbounds %struct.Bar* %8, i32 0, i32 0
store i8* null, i8** %p, align 8, !tbaa !3
%9 = load %struct.Foo** %f, align 8, !tbaa !3
%10 = bitcast %struct.Foo* %9 to i8*
%new.isnull2 = icmp eq i8* %10, null
br i1 %new.isnull2, label %new.cont4, label %new.notnull3
new.notnull3:
%11 = bitcast i8* %10 to %struct.Foo*
br label %new.cont4
new.cont4:
%12 = phi %struct.Foo* [ %11, %new.notnull3 ], [ null, %new.cont ]
store %struct.Foo* %12, %struct.Foo** %f, align 8, !tbaa !3
%13 = load i32* %i1, align 4, !tbaa !0
%conv = sext i32 %13 to i64
%14 = load %struct.Foo** %f, align 8, !tbaa !3
%i5 = getelementptr inbounds %struct.Foo* %14, i32 0, i32 0
store i64 %conv, i64* %i5, align 8, !tbaa !4
br label %for.inc
for.inc:
%15 = load i32* %i1, align 4, !tbaa !0
%inc = add nsw i32 %15, 1
store i32 %inc, i32* %i1, align 4, !tbaa !0
br label %for.cond
for.end:
%16 = load %struct.Foo** %f, align 8, !tbaa !3
%i6 = getelementptr inbounds %struct.Foo* %16, i32 0, i32 0
%17 = load i64* %i6, align 8, !tbaa !4
ret i64 %17
}
declare noalias i8* @_Znwm(i64)
attributes #0 = { nounwind }
!0 = metadata !{metadata !"int", metadata !1}
!1 = metadata !{metadata !"omnipotent char", metadata !2}
!2 = metadata !{metadata !"Simple C/C++ TBAA"}
!3 = metadata !{metadata !"any pointer", metadata !1}
!4 = metadata !{metadata !"long", metadata !1}