1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

Reintroduce the InlineHint function attribute.

This time it's for real! I am going to hook this up in the frontends as well.

The inliner has some experimental heuristics for dealing with the inline hint.
When given a -respect-inlinehint option, functions marked with the inline
keyword are given a threshold just above the default for -O3.

We need some experiments to determine if that is the right thing to do.

llvm-svn: 95466
This commit is contained in:
Jakob Stoklund Olesen 2010-02-06 01:16:28 +00:00
parent 60fb5a2446
commit 83ebc265b3
14 changed files with 48 additions and 13 deletions

View File

@ -93,6 +93,7 @@ module Attribute = struct
| Noredzone
| Noimplicitfloat
| Naked
| Inlinehint
end
module Icmp = struct

View File

@ -143,6 +143,7 @@ module Attribute : sig
| Noredzone
| Noimplicitfloat
| Naked
| Inlinehint
end
(** The predicate for an integer comparison ([icmp]) instruction.

View File

@ -1083,6 +1083,11 @@ define void @f() optsize { ... }
function into callers whenever possible, ignoring any active inlining size
threshold for this caller.</dd>
<dt><tt><b>inlinehint</b></tt></dt>
<dd>This attribute indicates that the source code contained a hint that inlining
this function is desirable (such as the "inline" keyword in C/C++). It
is just a hint; it imposes no requirements on the inliner.</dd>
<dt><tt><b>noinline</b></tt></dt>
<dd>This attribute indicates that the inliner should never inline this
function in any situation. This attribute may not be used together with

View File

@ -118,7 +118,8 @@ typedef enum {
LLVMNoCaptureAttribute = 1<<21,
LLVMNoRedZoneAttribute = 1<<22,
LLVMNoImplicitFloatAttribute = 1<<23,
LLVMNakedAttribute = 1<<24
LLVMNakedAttribute = 1<<24,
LLVMInlineHintAttribute = 1<<25
} LLVMAttribute;
typedef enum {

View File

@ -58,6 +58,8 @@ const Attributes NoRedZone = 1<<22; /// disable redzone
const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point
/// instructions.
const Attributes Naked = 1<<24; ///< Naked function
const Attributes InlineHint = 1<<25; ///< source said inlining was
///desirable
/// @brief Attributes that only apply to function parameters.
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
@ -66,7 +68,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
/// be used on return values or function parameters.
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
NoRedZone | NoImplicitFloat | Naked;
NoRedZone | NoImplicitFloat | Naked | InlineHint;
/// @brief Parameter attributes that do not apply to vararg call arguments.
const Attributes VarArgsIncompatible = StructRet;

View File

@ -52,10 +52,11 @@ struct Inliner : public CallGraphSCCPass {
unsigned getInlineThreshold() const { return InlineThreshold; }
/// Calculate the inline threshold for given Caller. This threshold is lower
/// if Caller is marked with OptimizeForSize and -inline-threshold is not
/// given on the comand line.
/// if the caller is marked with OptimizeForSize and -inline-threshold is not
/// given on the comand line. It is higher if the callee is marked with the
/// inlinehint attribute.
///
unsigned getInlineThreshold(Function* Caller) const;
unsigned getInlineThreshold(CallSite CS) const;
/// getInlineCost - This method must be implemented by the subclass to
/// determine the cost of inlining the specified call site. If the cost

View File

@ -558,6 +558,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(readnone);
KEYWORD(readonly);
KEYWORD(inlinehint);
KEYWORD(noinline);
KEYWORD(alwaysinline);
KEYWORD(optsize);

View File

@ -947,6 +947,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) {
case lltok::kw_noinline: Attrs |= Attribute::NoInline; break;
case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break;
case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break;
case lltok::kw_inlinehint: Attrs |= Attribute::InlineHint; break;
case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break;
case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break;
case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break;

View File

@ -85,6 +85,7 @@ namespace lltok {
kw_readnone,
kw_readonly,
kw_inlinehint,
kw_noinline,
kw_alwaysinline,
kw_optsize,

View File

@ -470,6 +470,7 @@ namespace {
HANDLE_ATTR(Nest);
HANDLE_ATTR(ReadNone);
HANDLE_ATTR(ReadOnly);
HANDLE_ATTR(InlineHint);
HANDLE_ATTR(NoInline);
HANDLE_ATTR(AlwaysInline);
HANDLE_ATTR(OptimizeForSize);

View File

@ -41,6 +41,16 @@ static cl::opt<int>
InlineLimit("inline-threshold", cl::Hidden, cl::init(225), cl::ZeroOrMore,
cl::desc("Control the amount of inlining to perform (default = 225)"));
static cl::opt<bool>
RespectHint("respect-inlinehint", cl::Hidden,
cl::desc("Respect the inlinehint attribute"));
// Threshold to use when inlinehint is given.
const int HintThreshold = 300;
// Threshold to use when optsize is specified (and there is no -inline-limit).
const int OptSizeThreshold = 75;
Inliner::Inliner(void *ID)
: CallGraphSCCPass(ID), InlineThreshold(InlineLimit) {}
@ -172,13 +182,21 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
return true;
}
unsigned Inliner::getInlineThreshold(Function* Caller) const {
unsigned Inliner::getInlineThreshold(CallSite CS) const {
// Listen to inlinehint when -respect-inlinehint is given.
Function *Callee = CS.getCalledFunction();
if (RespectHint && Callee && !Callee->isDeclaration() &&
Callee->hasFnAttr(Attribute::InlineHint))
return HintThreshold;
// Listen to optsize when -inline-limit is not given.
Function *Caller = CS.getCaller();
if (Caller && !Caller->isDeclaration() &&
Caller->hasFnAttr(Attribute::OptimizeForSize) &&
InlineLimit.getNumOccurrences() == 0)
return 75;
else
return InlineThreshold;
return OptSizeThreshold;
return InlineThreshold;
}
/// shouldInline - Return true if the inliner should attempt to inline
@ -200,7 +218,7 @@ bool Inliner::shouldInline(CallSite CS) {
int Cost = IC.getValue();
Function *Caller = CS.getCaller();
int CurrentThreshold = getInlineThreshold(Caller);
int CurrentThreshold = getInlineThreshold(CS);
float FudgeFactor = getInlineFudgeFactor(CS);
if (Cost >= (int)(CurrentThreshold * FudgeFactor)) {
DEBUG(dbgs() << " NOT Inlining: cost=" << Cost
@ -236,8 +254,7 @@ bool Inliner::shouldInline(CallSite CS) {
outerCallsFound = true;
int Cost2 = IC2.getValue();
Function *Caller2 = CS2.getCaller();
int CurrentThreshold2 = getInlineThreshold(Caller2);
int CurrentThreshold2 = getInlineThreshold(CS2);
float FudgeFactor2 = getInlineFudgeFactor(CS2);
if (Cost2 >= (int)(CurrentThreshold2 * FudgeFactor2))

View File

@ -56,6 +56,8 @@ std::string Attribute::getAsString(Attributes Attrs) {
Result += "optsize ";
if (Attrs & Attribute::NoInline)
Result += "noinline ";
if (Attrs & Attribute::InlineHint)
Result += "inlinehint ";
if (Attrs & Attribute::AlwaysInline)
Result += "alwaysinline ";
if (Attrs & Attribute::StackProtect)

View File

@ -161,6 +161,7 @@ FuncAttr ::= noreturn
| signext
| readnone
| readonly
| inlinehint
| noinline
| alwaysinline
| optsize

View File

@ -51,7 +51,7 @@ syn keyword llvmKeyword volatile fastcc coldcc cc ccc
syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
syn keyword llvmKeyword noinline alwaysinline optsize ssp sspreq
syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
syn keyword llvmKeyword noredzone noimplicitfloat naked
syn keyword llvmKeyword module asm align tail to
syn keyword llvmKeyword addrspace section alias sideeffect c gc