Extend the 'noalias' attribute to function return values. This is intended to

indicate functions that allocate, such as operator new, or list::insert. The
actual definition is slightly less strict (for now).

No changes to the bitcode reader/writer, asm printer or verifier were needed.

llvm-svn: 59934
This commit is contained in:
Nick Lewycky 2008-11-24 03:41:24 +00:00
parent e4b95698df
commit f5ffcbcd0b
6 changed files with 1415 additions and 1378 deletions

View File

@ -890,10 +890,11 @@ declare signext i8 @returns_signed_char()
return values. </dd>
<dt><tt>noalias</tt></dt>
<dd>This indicates that the parameter does not alias any global or any other
parameter. The caller is responsible for ensuring that this is the case,
usually by placing the value in a stack allocation. This is not a valid
attribute for return values.</dd>
<dd>This indicates that the pointer does not alias any global or any other
parameter. The caller is responsible for ensuring that this is the
case. Additionally, on a function return value <tt>noalias</tt> indicates
that the pointer does not alias the return value from other calls of
itself or other noalias functions.</dd>
<dt><tt>nest</tt></dt>
<dd>This indicates that the pointer parameter can be excised using the
@ -3155,7 +3156,7 @@ choose to align the allocation on any convenient boundary.</p>
<h5>Semantics:</h5>
<p>Memory is allocated using the system "<tt>malloc</tt>" function, and
a pointer is returned. The result of a zero byte allocattion is undefined. The
a pointer is returned. The result of a zero byte allocation is undefined. The
result is null if there is insufficient memory available.</p>
<h5>Example:</h5>

View File

@ -104,14 +104,24 @@ static const Value *GetGEPOperands(const Value *V,
return V;
}
/// isNoAliasCall - Return true if this pointer is returned by a noalias
/// function.
static bool isNoAliasCall(const Value *V) {
if (isa<CallInst>(V) || isa<InvokeInst>(V))
return CallSite(const_cast<Instruction*>(cast<Instruction>(V)))
.paramHasAttr(0, Attribute::NoAlias);
return false;
}
/// isIdentifiedObject - Return true if this pointer refers to a distinct and
/// identifiable object. This returns true for:
/// Global Variables and Functions
/// Allocas and Mallocs
/// ByVal and NoAlias Arguments
/// NoAlias returns
///
static bool isIdentifiedObject(const Value *V) {
if (isa<GlobalValue>(V) || isa<AllocationInst>(V))
if (isa<GlobalValue>(V) || isa<AllocationInst>(V) || isNoAliasCall(V))
return true;
if (const Argument *A = dyn_cast<Argument>(V))
return A->hasNoAliasAttr() || A->hasByValAttr();
@ -138,7 +148,7 @@ static bool isKnownNonNull(const Value *V) {
/// object that never escapes from the function.
static bool isNonEscapingLocalObject(const Value *V) {
// If this is a local allocation, check to see if it escapes.
if (isa<AllocationInst>(V))
if (isa<AllocationInst>(V) || isNoAliasCall(V))
return !AddressMightEscape(V);
// If this is an argument that corresponds to a byval or noalias argument,
@ -355,8 +365,7 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
// Are we checking for alias of the same value?
if (V1 == V2) return MustAlias;
if ((!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType())) &&
V1->getType() != Type::Int64Ty && V2->getType() != Type::Int64Ty)
if (!isa<PointerType>(V1->getType()) || !isa<PointerType>(V2->getType()))
return NoAlias; // Scalars cannot alias each other
// Strip off cast instructions...
@ -374,11 +383,11 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
return NoAlias;
// Incoming argument cannot alias locally allocated object!
if ((isa<Argument>(O1) && isa<AllocationInst>(O2)) ||
(isa<Argument>(O2) && isa<AllocationInst>(O1)))
// Local allocations can't alias with arguments or noalias functions.
if ((isa<AllocationInst>(O1) && (isa<Argument>(O2) || isNoAliasCall(O2))) ||
(isa<AllocationInst>(O2) && (isa<Argument>(O1) || isNoAliasCall(O1))))
return NoAlias;
// Most objects can't alias null.
if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) ||
(isa<ConstantPointerNull>(V1) && isKnownNonNull(O2)))

File diff suppressed because it is too large Load Diff

View File

@ -1284,9 +1284,10 @@ OptAttributes : /* empty */ { $$ = Attribute::None; }
}
;
RetAttr : INREG { $$ = Attribute::InReg; }
RetAttr : INREG { $$ = Attribute::InReg; }
| ZEROEXT { $$ = Attribute::ZExt; }
| SIGNEXT { $$ = Attribute::SExt; }
| NOALIAS { $$ = Attribute::NoAlias; }
;
OptRetAttrs : /* empty */ { $$ = Attribute::None; }

View File

@ -0,0 +1,12 @@
; RUN: llvm-as < %s | opt -aa-eval |& grep {1 no alias response}
declare noalias i32* @_Znwj(i32 %x) nounwind
define i32 @foo() {
%A = call i32* @_Znwj(i32 4)
%B = call i32* @_Znwj(i32 4)
store i32 1, i32* %A
store i32 2, i32* %B
%C = load i32* %A
ret i32 %C
}

View File

@ -0,0 +1,6 @@
; RUN: llvm-as < %s
define noalias i8* @_Znwj(i32 %x) nounwind {
%A = malloc i8, i32 %x
ret i8* %A
}