From 406bfa3e21e8fab3deab240c30c763e78eddf2f5 Mon Sep 17 00:00:00 2001 From: Christopher Lamb Date: Thu, 2 Aug 2007 01:18:14 +0000 Subject: [PATCH] Teach BasicAA about noalias parameter attributes, but do it correctly this time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40711 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/BasicAliasAnalysis.cpp | 32 ++++++++++++++++++- .../BasicAA/2007-08-01-NoAliasAndCalls.ll | 10 ++++++ .../BasicAA/2007-08-01-NoAliasAndGEP.ll | 17 ++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/Analysis/BasicAA/2007-08-01-NoAliasAndCalls.ll create mode 100644 test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 580f7e5d9e4..39f232e3e56 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -18,6 +18,7 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Function.h" +#include "llvm/ParameterAttributes.h" #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/Pass.h" @@ -260,6 +261,21 @@ BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { return AliasAnalysis::getModRefInfo(CS, P, Size); } +static bool isNoAliasArgument(const Argument *Arg) { + const Function *Func = Arg->getParent(); + const ParamAttrsList *Attr = Func->getFunctionType()->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. :) @@ -298,10 +314,24 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size, if (isa(O1)) { // Incoming argument cannot alias locally allocated object! if (isa(O2)) return NoAlias; + + // If they are two different objects, and one is a noalias argument + // then they do not alias. + if (O1 != O2 && isNoAliasArgument(cast(O1))) + return NoAlias; + // Otherwise, nothing is known... - } else if (isa(O2)) { + } + + if (isa(O2)) { // Incoming argument cannot alias locally allocated object! if (isa(O1)) return NoAlias; + + // If they are two different objects, and one is a noalias argument + // then they do not alias. + if (O1 != O2 && isNoAliasArgument(cast(O2))) + return NoAlias; + // Otherwise, nothing is known... } else if (O1 != O2) { // If they are two different objects, we know that we have no alias... diff --git a/test/Analysis/BasicAA/2007-08-01-NoAliasAndCalls.ll b/test/Analysis/BasicAA/2007-08-01-NoAliasAndCalls.ll new file mode 100644 index 00000000000..072bfd9fe9c --- /dev/null +++ b/test/Analysis/BasicAA/2007-08-01-NoAliasAndCalls.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as %s -o - | opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output &| grep 'MayAlias: i32* %y, i32* %x' + +declare i32* @unclear(i32* %a) + +define void @foo(i32* noalias %x) { + %y = call i32* @unclear(i32* %x) + store i32 0, i32* %x + store i32 0, i32* %y + ret void +} diff --git a/test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll b/test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll new file mode 100644 index 00000000000..8cc9f061d93 --- /dev/null +++ b/test/Analysis/BasicAA/2007-08-01-NoAliasAndGEP.ll @@ -0,0 +1,17 @@ +; RUN: llvm-as %s -o - | opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output &| grep '9 no alias' +; RUN: llvm-as %s -o - | opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output &| grep '6 may alias' +; RUN: llvm-as %s -o - | opt -basicaa -aa-eval -print-all-alias-modref-info -disable-output &| grep 'MayAlias: i32* %pj, i32* %pi' + +define void @foo(i32* noalias %p, i32* noalias %q, i32 %i, i32 %j) { + %pi = getelementptr i32* %p, i32 %i + %qi = getelementptr i32* %q, i32 %i + %pj = getelementptr i32* %p, i32 %j + %qj = getelementptr i32* %q, i32 %j + store i32 0, i32* %p + store i32 0, i32* %pi + store i32 0, i32* %pj + store i32 0, i32* %q + store i32 0, i32* %qi + store i32 0, i32* %qj + ret void +} -- 2.34.1