Implement function notes as function attributes.

llvm-svn: 56716
This commit is contained in:
Devang Patel 2008-09-26 23:51:19 +00:00
parent c4b02eb4e5
commit 9eb525d4f9
17 changed files with 92 additions and 178 deletions

View File

@ -26,8 +26,8 @@
<li><a href="#functionstructure">Functions</a></li>
<li><a href="#aliasstructure">Aliases</a>
<li><a href="#paramattrs">Parameter Attributes</a></li>
<li><a href="#fnattrs">Function Attributes</a></li>
<li><a href="#gc">Garbage Collector Names</a></li>
<li><a href="#notes">Function Notes</a></li>
<li><a href="#moduleasm">Module-Level Inline Assembly</a></li>
<li><a href="#datalayout">Data Layout</a></li>
</ol>
@ -826,8 +826,8 @@ a power of 2.</p>
<div class="doc_code">
<pre>
declare i32 @printf(i8* noalias , ...) nounwind
declare i32 @atoi(i8*) nounwind readonly
declare i32 @printf(i8* noalias , ...)
declare i32 @atoi(i8 zeroext*)
</pre>
</div>
@ -870,29 +870,9 @@ declare i32 @atoi(i8*) nounwind readonly
parameter. The caller is responsible for ensuring that this is the case,
usually by placing the value in a stack allocation.</dd>
<dt><tt>noreturn</tt></dt>
<dd>This function attribute indicates that the function never returns. This
indicates to LLVM that every call to this function should be treated as if
an <tt>unreachable</tt> instruction immediately followed the call.</dd>
<dt><tt>nounwind</tt></dt>
<dd>This function attribute indicates that no exceptions unwind out of the
function. Usually this is because the function makes no use of exceptions,
but it may also be that the function catches any exceptions thrown when
executing it.</dd>
<dt><tt>nest</tt></dt>
<dd>This indicates that the pointer parameter can be excised using the
<a href="#int_trampoline">trampoline intrinsics</a>.</dd>
<dt><tt>readonly</tt></dt>
<dd>This function attribute indicates that the function has no side-effects
except for producing a return value or throwing an exception. The value
returned must only depend on the function arguments and/or global variables.
It may use values obtained by dereferencing pointers.</dd>
<dt><tt>readnone</tt></dt>
<dd>A <tt>readnone</tt> function has the same restrictions as a <tt>readonly</tt>
function, but in addition it is not allowed to dereference any pointer arguments
or global variables.
</dl>
</div>
@ -916,38 +896,65 @@ the named garbage collection algorithm.</p>
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="notes">Function Notes</a>
<a name="fnattrs">Function Attributes</a>
</div>
<div class="doc_text">
<p>The function definition may list function notes which are used by
various passes.</p>
<p>Function attributes are set to communicate additional information about
a function. Function attributes are considered to be part of the function,
not of the function type, so functions with different parameter attributes
can have the same function type.</p>
<p>Function attributes are simple keywords that follow the type specified. If
multiple attributes are needed, they are space separated. For
example:</p>
<div class="doc_code">
<pre>
define void @f() notes(inline=Always) { ... }
define void @f() notes(inline=Always,opt-size) { ... }
define void @f() notes(inline=Never,opt-size) { ... }
define void @f() notes(opt-size) { ... }
define void @f() noinline { ... }
define void @f() alwaysinline { ... }
define void @f() alwaysinline optsize { ... }
define void @f() optsize
</pre>
</div>
<dl>
<dt><tt>inline=Always</tt></dt>
<dd>This note requests inliner to inline this function irrespective of inlining
size threshold for this function.</dd>
<dt><tt>alwaysinline</tt></dt>
<dd>This attribute requests inliner to inline this function irrespective of
inlining size threshold for this function.</dd>
<dt><tt>inline=Never</tt></dt>
<dd>This note requests inliner to never inline this function in any situation.
This note may not be used together with <tt>inline=Always</tt> note.</dd>
<dt><tt>noinline</tt></dt>
<dd>This attributes requests inliner to never inline this function in any
situation. This attribute may not be used together with <tt>alwaysinline</tt>
attribute.</dd>
<dt><tt>opt-size</tt></dt>
<dd>This note suggests optimization passes and code generator passes to make
choices that help reduce code size.</dd>
<dt><tt>optsize</tt></dt>
<dd>This attribute suggests optimization passes and code generator passes to
make choices that help reduce code size.</dd>
<dt><tt>noreturn</tt></dt>
<dd>This function attribute indicates that the function never returns. This
indicates to LLVM that every call to this function should be treated as if
an <tt>unreachable</tt> instruction immediately followed the call.</dd>
<dt><tt>nounwind</tt></dt>
<dd>This function attribute indicates that no exceptions unwind out of the
function. Usually this is because the function makes no use of exceptions,
but it may also be that the function catches any exceptions thrown when
executing it.</dd>
<dt><tt>readonly</tt></dt>
<dd>This function attribute indicates that the function has no side-effects
except for producing a return value or throwing an exception. The value
returned must only depend on the function arguments and/or global variables.
It may use values obtained by dereferencing pointers.</dd>
<dt><tt>readnone</tt></dt>
<dd>A <tt>readnone</tt> function has the same restrictions as a <tt>readonly</tt>
function, but in addition it is not allowed to dereference any pointer arguments
or global variables.
</dl>
<p>Any notes that are not documented here are considered invalid notes.</p>
</div>
<!-- ======================================================================= -->

View File

@ -149,16 +149,16 @@ public:
void setAttributes(const AttrListPtr &attrs) { AttributeList = attrs; }
/// hasNote - Return true if this function has given note.
bool hasNote(Attributes N) const {
// Notes are stored at ~0 index in parameter attribute list
return (paramHasAttr(~0, N));
/// hasFnAttr - Return true if this function has given attribute.
bool hasFnAttr(Attributes N) const {
// Function Attributes are stored at ~0 index
return AttributeList.paramHasAttr(~0U, N);
}
/// setNotes - Set notes for this function
/// addFnAttr - Add function attributes
///
void setNotes(const Attributes N) {
// Notes are stored at ~0 index in parameter attribute list
void addFnAttr(const Attributes N) {
// Function Attributes are stored at ~0 index
addAttribute(~0, N);
}

View File

@ -496,11 +496,9 @@ int LLLexer::LexIdentifier() {
KEYWORD("readnone", READNONE);
KEYWORD("readonly", READONLY);
KEYWORD("notes", FNNOTE);
KEYWORD("inline", INLINE);
KEYWORD("always", ALWAYS);
KEYWORD("never", NEVER);
KEYWORD("opt_size", OPTIMIZEFORSIZE);
KEYWORD("noinline", NOINLINE);
KEYWORD("alwaysinline", ALWAYSINLINE);
KEYWORD("optsize", OPTSIZE);
KEYWORD("type", TYPE);
KEYWORD("opaque", OPAQUE);

View File

@ -189,14 +189,12 @@
READNONE = 405,
READONLY = 406,
GC = 407,
FNNOTE = 408,
INLINE = 409,
ALWAYS = 410,
NEVER = 411,
OPTIMIZEFORSIZE = 412,
DEFAULT = 413,
HIDDEN = 414,
PROTECTED = 415
OPTSIZE = 408,
NOINLINE = 409,
ALWAYSINLINE = 410,
DEFAULT = 411,
HIDDEN = 412,
PROTECTED = 413
};
#endif
/* Tokens. */
@ -350,21 +348,19 @@
#define READNONE 405
#define READONLY 406
#define GC 407
#define FNNOTE 408
#define INLINE 409
#define ALWAYS 410
#define NEVER 411
#define OPTIMIZEFORSIZE 412
#define DEFAULT 413
#define HIDDEN 414
#define PROTECTED 415
#define OPTSIZE 408
#define NOINLINE 409
#define ALWAYSINLINE 410
#define DEFAULT 411
#define HIDDEN 412
#define PROTECTED 413
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
#line 970 "/Volumes/MacOS9/gcc/llvm/lib/AsmParser/llvmAsmParser.y"
#line 970 "/Volumes/Nanpura/mainline/llvm/lib/AsmParser/llvmAsmParser.y"
{
llvm::Module *ModuleVal;
llvm::Function *FunctionVal;
@ -413,7 +409,7 @@ typedef union YYSTYPE
llvm::FCmpInst::Predicate FPredicate;
}
/* Line 1529 of yacc.c. */
#line 417 "llvmAsmParser.tab.h"
#line 413 "llvmAsmParser.tab.h"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1

View File

@ -1089,8 +1089,6 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <UIntVal> OptCallingConv LocalNumber
%type <Attributes> OptAttributes Attribute
%type <Attributes> OptFuncAttrs FuncAttr
%type <Attributes> OptFuncNotes FuncNote
%type <Attributes> FuncNoteList
// Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
@ -1122,10 +1120,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
// Function Attributes
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
%token READNONE READONLY GC
// Function Notes
%token FNNOTE INLINE ALWAYS NEVER OPTIMIZEFORSIZE
%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE
// Visibility Styles
%token DEFAULT HIDDEN PROTECTED
@ -1284,6 +1279,9 @@ FuncAttr : NORETURN { $$ = Attribute::NoReturn; }
| SIGNEXT { $$ = Attribute::SExt; }
| READNONE { $$ = Attribute::ReadNone; }
| READONLY { $$ = Attribute::ReadOnly; }
| NOINLINE { $$ = Attribute::NoInline }
| ALWAYSINLINE { $$ = Attribute::AlwaysInline }
| OPTSIZE { $$ = Attribute::OptimizeForSize }
;
OptFuncAttrs : /* empty */ { $$ = Attribute::None; }
@ -1292,31 +1290,6 @@ OptFuncAttrs : /* empty */ { $$ = Attribute::None; }
}
;
FuncNoteList : FuncNote { $$ = $1; }
| FuncNoteList ',' FuncNote {
unsigned tmp = $1 | $3;
if ($3 == Attribute::NoInline
&& ($1 & Attribute::AlwaysInline))
GEN_ERROR("Function Notes may include only one inline notes!")
if ($3 == Attribute::AlwaysInline
&& ($1 & Attribute::NoInline))
GEN_ERROR("Function Notes may include only one inline notes!")
$$ = tmp;
CHECK_FOR_ERROR
}
;
FuncNote : INLINE '=' NEVER { $$ = Attribute::NoInline; }
| INLINE '=' ALWAYS { $$ = Attribute::AlwaysInline; }
| OPTIMIZEFORSIZE { $$ = Attribute::OptimizeForSize; }
;
OptFuncNotes : /* empty */ { $$ = Attribute::None; }
| FNNOTE '(' FuncNoteList ')' {
$$ = $3;
}
;
OptGC : /* empty */ { $$ = 0; }
| GC STRINGCONSTANT {
$$ = $2;
@ -2332,7 +2305,7 @@ ArgList : ArgListH {
};
FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
OptFuncAttrs OptSection OptAlign OptGC OptFuncNotes {
OptFuncAttrs OptSection OptAlign OptGC {
std::string FunctionName(*$3);
delete $3; // Free strdup'd memory!
@ -2453,9 +2426,6 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Fn->setGC($10->c_str());
delete $10;
}
if ($11) {
Fn->setNotes($11);
}
// Add all of the arguments we parsed to the function...
if ($5) { // Is null if empty...

View File

@ -1089,8 +1089,6 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
%type <UIntVal> OptCallingConv LocalNumber
%type <Attributes> OptAttributes Attribute
%type <Attributes> OptFuncAttrs FuncAttr
%type <Attributes> OptFuncNotes FuncNote
%type <Attributes> FuncNoteList
// Basic Block Terminating Operators
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
@ -1122,10 +1120,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
// Function Attributes
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
%token READNONE READONLY GC
// Function Notes
%token FNNOTE INLINE ALWAYS NEVER OPTIMIZEFORSIZE
%token READNONE READONLY GC OPTSIZE NOINLINE ALWAYSINLINE
// Visibility Styles
%token DEFAULT HIDDEN PROTECTED
@ -1284,6 +1279,9 @@ FuncAttr : NORETURN { $$ = Attribute::NoReturn; }
| SIGNEXT { $$ = Attribute::SExt; }
| READNONE { $$ = Attribute::ReadNone; }
| READONLY { $$ = Attribute::ReadOnly; }
| NOINLINE { $$ = Attribute::NoInline }
| ALWAYSINLINE { $$ = Attribute::AlwaysInline }
| OPTSIZE { $$ = Attribute::OptimizeForSize }
;
OptFuncAttrs : /* empty */ { $$ = Attribute::None; }
@ -1292,31 +1290,6 @@ OptFuncAttrs : /* empty */ { $$ = Attribute::None; }
}
;
FuncNoteList : FuncNote { $$ = $1; }
| FuncNoteList ',' FuncNote {
unsigned tmp = $1 | $3;
if ($3 == Attribute::NoInline
&& ($1 & Attribute::AlwaysInline))
GEN_ERROR("Function Notes may include only one inline notes!")
if ($3 == Attribute::AlwaysInline
&& ($1 & Attribute::NoInline))
GEN_ERROR("Function Notes may include only one inline notes!")
$$ = tmp;
CHECK_FOR_ERROR
}
;
FuncNote : INLINE '=' NEVER { $$ = Attribute::NoInline; }
| INLINE '=' ALWAYS { $$ = Attribute::AlwaysInline; }
| OPTIMIZEFORSIZE { $$ = Attribute::OptimizeForSize; }
;
OptFuncNotes : /* empty */ { $$ = Attribute::None; }
| FNNOTE '(' FuncNoteList ')' {
$$ = $3;
}
;
OptGC : /* empty */ { $$ = 0; }
| GC STRINGCONSTANT {
$$ = $2;
@ -2332,7 +2305,7 @@ ArgList : ArgListH {
};
FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
OptFuncAttrs OptSection OptAlign OptGC OptFuncNotes {
OptFuncAttrs OptSection OptAlign OptGC {
std::string FunctionName(*$3);
delete $3; // Free strdup'd memory!
@ -2453,9 +2426,6 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
Fn->setGC($10->c_str());
delete $10;
}
if ($11) {
Fn->setNotes($11);
}
// Add all of the arguments we parsed to the function...
if ($5) { // Is null if empty...

View File

@ -154,7 +154,7 @@ void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
SwitchToSection(TAI->SectionForGlobal(F));
unsigned FnAlign = OptimizeForSize ? 1 : 4;
if (!F->isDeclaration() && F->hasNote(Attribute::OptimizeForSize))
if (!F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
FnAlign = 1;
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");

View File

@ -141,7 +141,7 @@ bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
SwitchToTextSection("_text", F);
unsigned FnAlign = OptimizeForSize ? 1 : 4;
if (!F->isDeclaration() && F->hasNote(Attribute::OptimizeForSize))
if (!F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
FnAlign = 1;
switch (F->getLinkage()) {
default: assert(0 && "Unsupported linkage type!");

View File

@ -63,7 +63,7 @@ bool AlwaysInliner::doInitialization(CallGraph &CG) {
for (Module::iterator I = M.begin(), E = M.end();
I != E; ++I)
if (!I->isDeclaration() && !I->hasNote(Attribute::AlwaysInline))
if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline))
NeverInline.insert(I);
return false;

View File

@ -65,7 +65,7 @@ bool SimpleInliner::doInitialization(CallGraph &CG) {
for (Module::iterator I = M.begin(), E = M.end();
I != E; ++I)
if (!I->isDeclaration() && I->hasNote(Attribute::NoInline))
if (!I->isDeclaration() && I->hasFnAttr(Attribute::NoInline))
NeverInline.insert(I);
// Get llvm.noinline

View File

@ -141,7 +141,8 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
int CurrentThreshold = InlineThreshold;
Function *Fn = CS.getCaller();
if (Fn && !Fn->isDeclaration() && Fn->hasNote(Attribute::OptimizeForSize)
if (Fn && !Fn->isDeclaration()
&& Fn->hasFnAttr(Attribute::OptimizeForSize)
&& InlineThreshold != 50) {
CurrentThreshold = 50;
}

View File

@ -430,7 +430,7 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val){
Function *F = loopHeader->getParent();
// Do not unswitch if the function is optimized for size.
if (!F->isDeclaration() && F->hasNote(Attribute::OptimizeForSize))
if (!F->isDeclaration() && F->hasFnAttr(Attribute::OptimizeForSize))
return false;
// Check to see if it would be profitable to unswitch current loop.

View File

@ -222,7 +222,7 @@ int InlineCostAnalyzer::getInlineCost(CallSite CS,
if (CalleeFI.NeverInline)
return 2000000000;
if (!Callee->isDeclaration() && Callee->hasNote(Attribute::AlwaysInline))
if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
return -2000000000;
// Add to the inline quality for properties that make the call valuable to

View File

@ -1413,34 +1413,6 @@ void AssemblyWriter::printFunction(const Function *F) {
if (F->isDeclaration()) {
Out << "\n";
} else {
bool insideNotes = false;
if (F->hasNote(Attribute::AlwaysInline)) {
Out << " notes(";
insideNotes = true;
Out << "inline=always";
}
if (F->hasNote(Attribute::NoInline)) {
if (insideNotes)
Out << ",";
else {
Out << " notes(";
insideNotes = true;
}
Out << "inline=never";
}
if (F->hasNote(Attribute::OptimizeForSize)) {
if (insideNotes)
Out << ",";
else {
Out << " notes(";
insideNotes = true;
}
Out << "opt_size";
}
if (insideNotes)
Out << ")";
Out << " {";
// Output all of its basic blocks... for the function

View File

@ -1,7 +1,7 @@
; RUN: llvm-as < %s | llc -march=arm
; RUN: llvm-as < %s | llc -march=thumb
define double @t(double %x, double %y) nounwind notes(opt_size) {
define double @t(double %x, double %y) nounwind optsize {
entry:
%0 = tail call double @llvm.pow.f64( double %x, double %y ) ; <double> [#uses=1]
ret double %0

View File

@ -1,6 +1,6 @@
; RUN: llvm-as < %s | opt -inline-threshold=0 -inline | llvm-dis | not grep call
define i32 @fn2() notes(inline=always) {
define i32 @fn2() alwaysinline {
ret i32 1
}

View File

@ -1,6 +1,6 @@
; RUN: llvm-as < %s | opt -inline | llvm-dis | grep call | count 1
define i32 @fn2() notes(inline=never) {
define i32 @fn2() noinline {
ret i32 1
}