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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59934 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky 2008-11-24 03:41:24 +00:00
parent 9f22a4aaaf
commit 02ff308aa1
6 changed files with 1415 additions and 1378 deletions

View File

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

View File

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