mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[ThinLTO] Split NotEligibleToImport into legality and inlinability flags
Summary: The NotEligibleToImport flag on the GlobalValueSummary was set if it isn't legal to import (e.g. because it references unpromotable locals) and when it can't be inlined (in which case importing is pointless). I split out the inlinable piece into a separate flag on the FunctionSummary (doesn't make sense for aliases or global variables), because in the future we may want to import for reasons other than inlining. Reviewers: davidxl Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits Differential Revision: https://reviews.llvm.org/D53345 llvm-svn: 346261
This commit is contained in:
parent
6b0730ff7f
commit
ea03f6009a
@ -478,13 +478,17 @@ public:
|
|||||||
TypeCheckedLoadConstVCalls;
|
TypeCheckedLoadConstVCalls;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Function attribute flags. Used to track if a function accesses memory,
|
/// Flags specific to function summaries.
|
||||||
/// recurses or aliases.
|
|
||||||
struct FFlags {
|
struct FFlags {
|
||||||
|
// Function attribute flags. Used to track if a function accesses memory,
|
||||||
|
// recurses or aliases.
|
||||||
unsigned ReadNone : 1;
|
unsigned ReadNone : 1;
|
||||||
unsigned ReadOnly : 1;
|
unsigned ReadOnly : 1;
|
||||||
unsigned NoRecurse : 1;
|
unsigned NoRecurse : 1;
|
||||||
unsigned ReturnDoesNotAlias : 1;
|
unsigned ReturnDoesNotAlias : 1;
|
||||||
|
|
||||||
|
// Indicate if the global value cannot be inlined.
|
||||||
|
unsigned NoInline : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create an empty FunctionSummary (with specified call edges).
|
/// Create an empty FunctionSummary (with specified call edges).
|
||||||
@ -511,8 +515,7 @@ private:
|
|||||||
/// during the initial compile step when the summary index is first built.
|
/// during the initial compile step when the summary index is first built.
|
||||||
unsigned InstCount;
|
unsigned InstCount;
|
||||||
|
|
||||||
/// Function attribute flags. Used to track if a function accesses memory,
|
/// Function summary specific flags.
|
||||||
/// recurses or aliases.
|
|
||||||
FFlags FunFlags;
|
FFlags FunFlags;
|
||||||
|
|
||||||
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
|
/// List of <CalleeValueInfo, CalleeInfo> call edge pairs from this function.
|
||||||
@ -546,7 +549,7 @@ public:
|
|||||||
return GVS->getSummaryKind() == FunctionKind;
|
return GVS->getSummaryKind() == FunctionKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get function attribute flags.
|
/// Get function summary flags.
|
||||||
FFlags fflags() const { return FunFlags; }
|
FFlags fflags() const { return FunFlags; }
|
||||||
|
|
||||||
/// Get the instruction count recorded for this function.
|
/// Get the instruction count recorded for this function.
|
||||||
|
@ -56,10 +56,14 @@ public:
|
|||||||
// to find at least one summary for the GUID that is global or a local
|
// to find at least one summary for the GUID that is global or a local
|
||||||
// in the referenced module for direct calls.
|
// in the referenced module for direct calls.
|
||||||
LocalLinkageNotInModule,
|
LocalLinkageNotInModule,
|
||||||
// This corresponse to the NotEligibleToImport being set on the summary,
|
// This corresponds to the NotEligibleToImport being set on the summary,
|
||||||
// which can happen in a few different cases (e.g. local that can't be
|
// which can happen in a few different cases (e.g. local that can't be
|
||||||
// renamed or promoted because it is referenced on a llvm*.used variable).
|
// renamed or promoted because it is referenced on a llvm*.used variable).
|
||||||
NotEligible
|
NotEligible,
|
||||||
|
// This corresponds to NoInline being set on the function summary,
|
||||||
|
// which will happen if it is known that the inliner will not be able
|
||||||
|
// to inline the function (e.g. it is marked with a NoInline attribute).
|
||||||
|
NoInline
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Information optionally tracked for candidates the importer decided
|
/// Information optionally tracked for candidates the importer decided
|
||||||
|
@ -350,20 +350,18 @@ static void computeFunctionSummary(
|
|||||||
|
|
||||||
bool NonRenamableLocal = isNonRenamableLocal(F);
|
bool NonRenamableLocal = isNonRenamableLocal(F);
|
||||||
bool NotEligibleForImport =
|
bool NotEligibleForImport =
|
||||||
NonRenamableLocal || HasInlineAsmMaybeReferencingInternal ||
|
NonRenamableLocal || HasInlineAsmMaybeReferencingInternal;
|
||||||
// Inliner doesn't handle variadic functions.
|
|
||||||
// FIXME: refactor this to use the same code that inliner is using.
|
|
||||||
F.isVarArg() ||
|
|
||||||
// Don't try to import functions with noinline attribute.
|
|
||||||
F.getAttributes().hasFnAttribute(Attribute::NoInline);
|
|
||||||
GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
|
GlobalValueSummary::GVFlags Flags(F.getLinkage(), NotEligibleForImport,
|
||||||
/* Live = */ false, F.isDSOLocal());
|
/* Live = */ false, F.isDSOLocal());
|
||||||
FunctionSummary::FFlags FunFlags{
|
FunctionSummary::FFlags FunFlags{
|
||||||
F.hasFnAttribute(Attribute::ReadNone),
|
F.hasFnAttribute(Attribute::ReadNone),
|
||||||
F.hasFnAttribute(Attribute::ReadOnly),
|
F.hasFnAttribute(Attribute::ReadOnly),
|
||||||
F.hasFnAttribute(Attribute::NoRecurse),
|
F.hasFnAttribute(Attribute::NoRecurse), F.returnDoesNotAlias(),
|
||||||
F.returnDoesNotAlias(),
|
// Inliner doesn't handle variadic functions.
|
||||||
};
|
// FIXME: refactor this to use the same code that inliner is using.
|
||||||
|
F.isVarArg() ||
|
||||||
|
// Don't try to import functions with noinline attribute.
|
||||||
|
F.getAttributes().hasFnAttribute(Attribute::NoInline)};
|
||||||
auto FuncSummary = llvm::make_unique<FunctionSummary>(
|
auto FuncSummary = llvm::make_unique<FunctionSummary>(
|
||||||
Flags, NumInsts, FunFlags, RefEdges.takeVector(),
|
Flags, NumInsts, FunFlags, RefEdges.takeVector(),
|
||||||
CallGraphEdges.takeVector(), TypeTests.takeVector(),
|
CallGraphEdges.takeVector(), TypeTests.takeVector(),
|
||||||
@ -478,7 +476,8 @@ ModuleSummaryIndex llvm::buildModuleSummaryIndex(
|
|||||||
F->hasFnAttribute(Attribute::ReadNone),
|
F->hasFnAttribute(Attribute::ReadNone),
|
||||||
F->hasFnAttribute(Attribute::ReadOnly),
|
F->hasFnAttribute(Attribute::ReadOnly),
|
||||||
F->hasFnAttribute(Attribute::NoRecurse),
|
F->hasFnAttribute(Attribute::NoRecurse),
|
||||||
F->returnDoesNotAlias()},
|
F->returnDoesNotAlias(),
|
||||||
|
/* NoInline = */ false},
|
||||||
ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
|
ArrayRef<ValueInfo>{}, ArrayRef<FunctionSummary::EdgeTy>{},
|
||||||
ArrayRef<GlobalValue::GUID>{},
|
ArrayRef<GlobalValue::GUID>{},
|
||||||
ArrayRef<FunctionSummary::VFuncId>{},
|
ArrayRef<FunctionSummary::VFuncId>{},
|
||||||
|
@ -740,6 +740,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
|||||||
KEYWORD(readOnly);
|
KEYWORD(readOnly);
|
||||||
KEYWORD(noRecurse);
|
KEYWORD(noRecurse);
|
||||||
KEYWORD(returnDoesNotAlias);
|
KEYWORD(returnDoesNotAlias);
|
||||||
|
KEYWORD(noInline);
|
||||||
KEYWORD(calls);
|
KEYWORD(calls);
|
||||||
KEYWORD(callee);
|
KEYWORD(callee);
|
||||||
KEYWORD(hotness);
|
KEYWORD(hotness);
|
||||||
|
@ -7714,6 +7714,7 @@ bool LLParser::ParseFlag(unsigned &Val) {
|
|||||||
/// := 'funcFlags' ':' '(' ['readNone' ':' Flag]?
|
/// := 'funcFlags' ':' '(' ['readNone' ':' Flag]?
|
||||||
/// [',' 'readOnly' ':' Flag]? [',' 'noRecurse' ':' Flag]?
|
/// [',' 'readOnly' ':' Flag]? [',' 'noRecurse' ':' Flag]?
|
||||||
/// [',' 'returnDoesNotAlias' ':' Flag]? ')'
|
/// [',' 'returnDoesNotAlias' ':' Flag]? ')'
|
||||||
|
/// [',' 'noInline' ':' Flag]? ')'
|
||||||
bool LLParser::ParseOptionalFFlags(FunctionSummary::FFlags &FFlags) {
|
bool LLParser::ParseOptionalFFlags(FunctionSummary::FFlags &FFlags) {
|
||||||
assert(Lex.getKind() == lltok::kw_funcFlags);
|
assert(Lex.getKind() == lltok::kw_funcFlags);
|
||||||
Lex.Lex();
|
Lex.Lex();
|
||||||
@ -7749,6 +7750,12 @@ bool LLParser::ParseOptionalFFlags(FunctionSummary::FFlags &FFlags) {
|
|||||||
return true;
|
return true;
|
||||||
FFlags.ReturnDoesNotAlias = Val;
|
FFlags.ReturnDoesNotAlias = Val;
|
||||||
break;
|
break;
|
||||||
|
case lltok::kw_noInline:
|
||||||
|
Lex.Lex();
|
||||||
|
if (ParseToken(lltok::colon, "expected ':'") || ParseFlag(Val))
|
||||||
|
return true;
|
||||||
|
FFlags.NoInline = Val;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return Error(Lex.getLoc(), "expected function flag type");
|
return Error(Lex.getLoc(), "expected function flag type");
|
||||||
}
|
}
|
||||||
|
@ -369,6 +369,7 @@ enum Kind {
|
|||||||
kw_readOnly,
|
kw_readOnly,
|
||||||
kw_noRecurse,
|
kw_noRecurse,
|
||||||
kw_returnDoesNotAlias,
|
kw_returnDoesNotAlias,
|
||||||
|
kw_noInline,
|
||||||
kw_calls,
|
kw_calls,
|
||||||
kw_callee,
|
kw_callee,
|
||||||
kw_hotness,
|
kw_hotness,
|
||||||
|
@ -876,6 +876,7 @@ static FunctionSummary::FFlags getDecodedFFlags(uint64_t RawFlags) {
|
|||||||
Flags.ReadOnly = (RawFlags >> 1) & 0x1;
|
Flags.ReadOnly = (RawFlags >> 1) & 0x1;
|
||||||
Flags.NoRecurse = (RawFlags >> 2) & 0x1;
|
Flags.NoRecurse = (RawFlags >> 2) & 0x1;
|
||||||
Flags.ReturnDoesNotAlias = (RawFlags >> 3) & 0x1;
|
Flags.ReturnDoesNotAlias = (RawFlags >> 3) & 0x1;
|
||||||
|
Flags.NoInline = (RawFlags >> 4) & 0x1;
|
||||||
return Flags;
|
return Flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -971,6 +971,7 @@ static uint64_t getEncodedFFlags(FunctionSummary::FFlags Flags) {
|
|||||||
RawFlags |= (Flags.ReadOnly << 1);
|
RawFlags |= (Flags.ReadOnly << 1);
|
||||||
RawFlags |= (Flags.NoRecurse << 2);
|
RawFlags |= (Flags.NoRecurse << 2);
|
||||||
RawFlags |= (Flags.ReturnDoesNotAlias << 3);
|
RawFlags |= (Flags.ReturnDoesNotAlias << 3);
|
||||||
|
RawFlags |= (Flags.NoInline << 4);
|
||||||
return RawFlags;
|
return RawFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2871,6 +2871,7 @@ void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) {
|
|||||||
Out << ", readOnly: " << FFlags.ReadOnly;
|
Out << ", readOnly: " << FFlags.ReadOnly;
|
||||||
Out << ", noRecurse: " << FFlags.NoRecurse;
|
Out << ", noRecurse: " << FFlags.NoRecurse;
|
||||||
Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
|
Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
|
||||||
|
Out << ", noInline: " << FFlags.NoInline;
|
||||||
Out << ")";
|
Out << ")";
|
||||||
}
|
}
|
||||||
if (!FS->calls().empty()) {
|
if (!FS->calls().empty()) {
|
||||||
|
@ -182,8 +182,9 @@ static std::string linkageToString(GlobalValue::LinkageTypes LT) {
|
|||||||
|
|
||||||
static std::string fflagsToString(FunctionSummary::FFlags F) {
|
static std::string fflagsToString(FunctionSummary::FFlags F) {
|
||||||
auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };
|
auto FlagValue = [](unsigned V) { return V ? '1' : '0'; };
|
||||||
char FlagRep[] = {FlagValue(F.ReadNone), FlagValue(F.ReadOnly),
|
char FlagRep[] = {FlagValue(F.ReadNone), FlagValue(F.ReadOnly),
|
||||||
FlagValue(F.NoRecurse), FlagValue(F.ReturnDoesNotAlias), 0};
|
FlagValue(F.NoRecurse), FlagValue(F.ReturnDoesNotAlias),
|
||||||
|
FlagValue(F.NoInline), 0};
|
||||||
|
|
||||||
return FlagRep;
|
return FlagRep;
|
||||||
}
|
}
|
||||||
|
@ -237,11 +237,19 @@ selectCallee(const ModuleSummaryIndex &Index,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip if it isn't legal to import (e.g. may reference unpromotable
|
||||||
|
// locals).
|
||||||
if (Summary->notEligibleToImport()) {
|
if (Summary->notEligibleToImport()) {
|
||||||
Reason = FunctionImporter::ImportFailureReason::NotEligible;
|
Reason = FunctionImporter::ImportFailureReason::NotEligible;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't bother importing if we can't inline it anyway.
|
||||||
|
if (Summary->fflags().NoInline) {
|
||||||
|
Reason = FunctionImporter::ImportFailureReason::NoInline;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (It == CalleeSummaryList.end())
|
if (It == CalleeSummaryList.end())
|
||||||
@ -318,6 +326,8 @@ getFailureName(FunctionImporter::ImportFailureReason Reason) {
|
|||||||
return "LocalLinkageNotInModule";
|
return "LocalLinkageNotInModule";
|
||||||
case FunctionImporter::ImportFailureReason::NotEligible:
|
case FunctionImporter::ImportFailureReason::NotEligible:
|
||||||
return "NotEligible";
|
return "NotEligible";
|
||||||
|
case FunctionImporter::ImportFailureReason::NoInline:
|
||||||
|
return "NoInline";
|
||||||
}
|
}
|
||||||
llvm_unreachable("invalid reason");
|
llvm_unreachable("invalid reason");
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@
|
|||||||
; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0))))
|
; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0))))
|
||||||
; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1))))
|
; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1))))
|
||||||
; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 1, live: 1, dsoLocal: 0), insts: 1)))
|
; CHECK: ^15 = gv: (guid: 14, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 1, live: 1, dsoLocal: 0), insts: 1)))
|
||||||
; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0))))
|
; CHECK: ^16 = gv: (guid: 15, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0))))
|
||||||
; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1), calls: ((callee: ^15)))))
|
; CHECK: ^17 = gv: (guid: 16, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1, funcFlags: (readNone: 0, readOnly: 1, noRecurse: 0, returnDoesNotAlias: 1, noInline: 0), calls: ((callee: ^15)))))
|
||||||
; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: ^14)))
|
; CHECK: ^18 = gv: (guid: 17, summaries: (alias: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: ^14)))
|
||||||
; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 4, typeIdInfo: (typeTests: (^24, ^26)))))
|
; CHECK: ^19 = gv: (guid: 18, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 4, typeIdInfo: (typeTests: (^24, ^26)))))
|
||||||
; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^27, offset: 16))))))
|
; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^27, offset: 16))))))
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0
|
; BC-NEXT: <PERMODULE {{.*}} op0=1 op1=0
|
||||||
; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0
|
; BC-NEXT: <PERMODULE {{.*}} op0=2 op1=0
|
||||||
; BC-NEXT: <PERMODULE {{.*}} op0=3 op1=7
|
; BC-NEXT: <PERMODULE {{.*}} op0=3 op1=7
|
||||||
; BC-NEXT: <PERMODULE {{.*}} op0=4 op1=16
|
; BC-NEXT: <PERMODULE {{.*}} op0=4 op1=0 op2=1 op3=16
|
||||||
; BC-NEXT: <ALIAS {{.*}} op0=5 op1=0 op2=3
|
; BC-NEXT: <ALIAS {{.*}} op0=5 op1=0 op2=3
|
||||||
; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK
|
; BC-NEXT: </GLOBALVAL_SUMMARY_BLOCK
|
||||||
; BC: <STRTAB_BLOCK
|
; BC: <STRTAB_BLOCK
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
; CLUSTER1: // Module: {{.*}}2.bc
|
; CLUSTER1: // Module: {{.*}}2.bc
|
||||||
; CLUSTER1-NEXT: subgraph cluster_1 {
|
; CLUSTER1-NEXT: subgraph cluster_1 {
|
||||||
; CLUSTER1-DAG: M1_[[A:[0-9]+]] [{{.*}}A|extern{{.*}}]; // variable
|
; CLUSTER1-DAG: M1_[[A:[0-9]+]] [{{.*}}A|extern{{.*}}]; // variable
|
||||||
; CLUSTER1-DAG: M1_[[FOO:[0-9]+]] [{{.*}}foo|extern{{.*}}]; // function, not eligible to import
|
; CLUSTER1-DAG: M1_[[FOO:[0-9]+]] [{{.*}}foo|extern{{.*}} ffl: 00001{{.*}}]; // function
|
||||||
; CLUSTER1-DAG: M1_[[B:[0-9]+]] [{{.*}}B|extern{{.*}}]; // variable
|
; CLUSTER1-DAG: M1_[[B:[0-9]+]] [{{.*}}B|extern{{.*}}]; // variable
|
||||||
; CLUSTER1-DAG: M1_[[BAR:[0-9]+]] [{{.*}}bar|extern{{.*}}]; // function, dead
|
; CLUSTER1-DAG: M1_[[BAR:[0-9]+]] [{{.*}}bar|extern{{.*}}]; // function, dead
|
||||||
; CLUSTER1-NEXT: // Edges:
|
; CLUSTER1-NEXT: // Edges:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user