diff options
| author | Chris Lattner <sabre@nondot.org> | 2008-01-24 18:00:32 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2008-01-24 18:00:32 +0000 | 
| commit | 9104d7126955550d74be71acd3319c802186ef82 (patch) | |
| tree | 742803b55756329b6d4a3c241d721942ad9c1f25 | |
| parent | e30f09d0c5158fd73b3f7b33d11ed8734f1f5a6d (diff) | |
| download | bcm5719-llvm-9104d7126955550d74be71acd3319c802186ef82.tar.gz bcm5719-llvm-9104d7126955550d74be71acd3319c802186ef82.zip  | |
Teach basicaa that 'byval' arguments define a new memory location that
can't be aliased to other known objects.  This allows us to know that byval 
pointer args don't alias globals, etc.
llvm-svn: 46315
| -rw-r--r-- | llvm/lib/Analysis/BasicAliasAnalysis.cpp | 68 | ||||
| -rw-r--r-- | llvm/test/Analysis/BasicAA/byval.ll | 18 | 
2 files changed, 52 insertions, 34 deletions
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp index 95278020a25..381298b86ea 100644 --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -138,9 +138,10 @@ ImmutablePass *llvm::createBasicAliasAnalysisPass() {    return new BasicAliasAnalysis();  } -// getUnderlyingObject - This traverses the use chain to figure out what object -// the specified value points to.  If the value points to, or is derived from, a -// unique object or an argument, return it. +/// getUnderlyingObject - This traverses the use chain to figure out what object +/// the specified value points to.  If the value points to, or is derived from, +/// a unique object or an argument, return it.  This returns: +///    Arguments, GlobalVariables, Functions, Allocas, Mallocs.  static const Value *getUnderlyingObject(const Value *V) {    if (!isa<PointerType>(V->getType())) return 0; @@ -241,41 +242,29 @@ static bool AddressMightEscape(const Value *V) {  //  AliasAnalysis::ModRefResult  BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { -  if (!isa<Constant>(P)) -    if (const AllocationInst *AI = -                  dyn_cast_or_null<AllocationInst>(getUnderlyingObject(P))) { +  if (!isa<Constant>(P)) { +    const Value *Object = getUnderlyingObject(P); +    // Allocations and byval arguments are "new" objects. +    if (isa<AllocationInst>(Object) || +        (isa<Argument>(Object) && cast<Argument>(Object)->hasByValAttr())) {        // Okay, the pointer is to a stack allocated object.  If we can prove that        // the pointer never "escapes", then we know the call cannot clobber it,        // because it simply can't get its address. -      if (!AddressMightEscape(AI)) +      if (!AddressMightEscape(Object))          return NoModRef;        // If this is a tail call and P points to a stack location, we know that        // the tail call cannot access or modify the local stack.        if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) -        if (CI->isTailCall() && isa<AllocaInst>(AI)) +        if (CI->isTailCall() && !isa<MallocInst>(Object))            return NoModRef;      } +  }    // The AliasAnalysis base class has some smarts, lets use them.    return AliasAnalysis::getModRefInfo(CS, P, Size);  } -static bool isNoAliasArgument(const Argument *Arg) { -  const Function *Func = Arg->getParent(); -  const ParamAttrsList *Attr = Func->getParamAttrs(); -  if (Attr) { -    unsigned Idx = 1; -    for (Function::const_arg_iterator I = Func->arg_begin(),  -          E = Func->arg_end(); I != E; ++I, ++Idx) { -      if (&(*I) == Arg &&  -           Attr->paramHasAttr(Idx, ParamAttr::NoAlias)) -        return true; -    } -  } -  return false; -} -  // alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such  // as array references.  Note that this function is heavily tail recursive.  // Hopefully we have a smart C++ compiler.  :) @@ -317,9 +306,12 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,          // If they are two different objects, and one is a noalias argument          // then they do not alias. -        if (O1 != O2 && isNoAliasArgument(O1Arg)) +        if (O1 != O2 && O1Arg->hasNoAliasAttr())            return NoAlias; -           + +        // Byval arguments can't alias globals or other arguments. +        if (O1 != O2 && O1Arg->hasByValAttr()) return NoAlias; +                  // Otherwise, nothing is known...        }  @@ -329,16 +321,18 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,          // If they are two different objects, and one is a noalias argument          // then they do not alias. -        if (O1 != O2 && isNoAliasArgument(O2Arg)) +        if (O1 != O2 && O2Arg->hasNoAliasAttr())            return NoAlias; +        // Byval arguments can't alias globals or other arguments. +        if (O1 != O2 && O2Arg->hasByValAttr()) return NoAlias; +                  // Otherwise, nothing is known... -      } else if (O1 != O2) { -        if (!isa<Argument>(O1)) -          // If they are two different objects, and neither is an argument, -          // we know that we have no alias... -          return NoAlias; +      } else if (O1 != O2 && !isa<Argument>(O1)) { +        // If they are two different objects, and neither is an argument, +        // we know that we have no alias. +        return NoAlias;        }        // If they are the same object, they we can look at the indexes.  If they @@ -347,9 +341,15 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,        // can't tell anything.      } - -    if (!isa<Argument>(O1) && isa<ConstantPointerNull>(V2)) -      return NoAlias;                    // Unique values don't alias null +    // Unique values don't alias null, except non-byval arguments. +    if (isa<ConstantPointerNull>(V2)) { +      if (const Argument *O1Arg = dyn_cast<Argument>(O1)) { +        if (O1Arg->hasByValAttr())  +          return NoAlias; +      } else { +        return NoAlias;                     +      } +    }      if (isa<GlobalVariable>(O1) ||          (isa<AllocationInst>(O1) && diff --git a/llvm/test/Analysis/BasicAA/byval.ll b/llvm/test/Analysis/BasicAA/byval.ll new file mode 100644 index 00000000000..f0644198b7d --- /dev/null +++ b/llvm/test/Analysis/BasicAA/byval.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | opt -gvn | llvm-dis | grep {ret i32 1} +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i686-apple-darwin8" +	%struct.x = type { i32, i32, i32, i32 } +@g = weak global i32 0		; <i32*> [#uses=1] + +define i32 @foo(%struct.x* byval  %a) nounwind  { +entry: +	%tmp1 = tail call i32 (...)* @bar( %struct.x* %a ) nounwind 		; <i32> [#uses=0] +	%tmp2 = getelementptr %struct.x* %a, i32 0, i32 0		; <i32*> [#uses=2] +	store i32 1, i32* %tmp2, align 4 +	store i32 2, i32* @g, align 4 +	%tmp4 = load i32* %tmp2, align 4		; <i32> [#uses=1] +	ret i32 %tmp4 +} + +declare i32 @bar(...) +  | 

