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

[ThinLTO] Assembly representation of ReadOnly attribute

Differential revision: https://reviews.llvm.org/D54754

llvm-svn: 347489
This commit is contained in:
Eugene Leviant 2018-11-23 10:54:51 +00:00
parent 99f7d361cb
commit e92db220ba
8 changed files with 88 additions and 37 deletions

View File

@ -788,6 +788,7 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(info);
KEYWORD(byte);
KEYWORD(bit);
KEYWORD(varFlags);
#undef KEYWORD

View File

@ -7470,8 +7470,14 @@ bool LLParser::ParseArgs(std::vector<uint64_t> &Args) {
return false;
}
static ValueInfo EmptyVI =
ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8);
auto FwdVIRef = (GlobalValueSummaryMapTy::value_type *)-8;
static void resolveFwdRef(ValueInfo *Fwd, ValueInfo &Resolved) {
bool ReadOnly = Fwd->isReadOnly();
*Fwd = Resolved;
if (ReadOnly)
Fwd->setReadOnly();
}
/// Stores the given Name/GUID and associated summary into the Index.
/// Also updates any forward references to the associated entry ID.
@ -7507,9 +7513,9 @@ void LLParser::AddGlobalValueToIndex(
auto FwdRefVIs = ForwardRefValueInfos.find(ID);
if (FwdRefVIs != ForwardRefValueInfos.end()) {
for (auto VIRef : FwdRefVIs->second) {
assert(*VIRef.first == EmptyVI &&
assert(VIRef.first->getRef() == FwdVIRef &&
"Forward referenced ValueInfo expected to be empty");
*VIRef.first = VI;
resolveFwdRef(VIRef.first, VI);
}
ForwardRefValueInfos.erase(FwdRefVIs);
}
@ -7699,11 +7705,14 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
GlobalValueSummary::GVFlags GVFlags = GlobalValueSummary::GVFlags(
/*Linkage=*/GlobalValue::ExternalLinkage, /*NotEligibleToImport=*/false,
/*Live=*/false, /*IsLocal=*/false);
GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);
std::vector<ValueInfo> Refs;
if (ParseToken(lltok::colon, "expected ':' here") ||
ParseToken(lltok::lparen, "expected '(' here") ||
ParseModuleReference(ModulePath) ||
ParseToken(lltok::comma, "expected ',' here") || ParseGVFlags(GVFlags))
ParseToken(lltok::comma, "expected ',' here") || ParseGVFlags(GVFlags) ||
ParseToken(lltok::comma, "expected ',' here") ||
ParseGVarFlags(GVarFlags))
return true;
// Parse optional refs field
@ -7715,8 +7724,8 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,
if (ParseToken(lltok::rparen, "expected ')' here"))
return true;
auto GS = llvm::make_unique<GlobalVarSummary>(
GVFlags, GlobalVarSummary::GVarFlags(), std::move(Refs));
auto GS =
llvm::make_unique<GlobalVarSummary>(GVFlags, GVarFlags, std::move(Refs));
GS->setModulePath(ModulePath);
@ -7761,7 +7770,7 @@ bool LLParser::ParseAliasSummary(std::string Name, GlobalValue::GUID GUID,
AS->setModulePath(ModulePath);
// Record forward reference if the aliasee is not parsed yet.
if (AliaseeVI == EmptyVI) {
if (AliaseeVI.getRef() == FwdVIRef) {
auto FwdRef = ForwardRefAliasees.insert(
std::make_pair(GVId, std::vector<std::pair<AliasSummary *, LocTy>>()));
FwdRef.first->second.push_back(std::make_pair(AS.get(), Loc));
@ -7883,7 +7892,7 @@ bool LLParser::ParseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls) {
// Keep track of the Call array index needing a forward reference.
// We will save the location of the ValueInfo needing an update, but
// can only do so once the std::vector is finalized.
if (VI == EmptyVI)
if (VI.getRef() == FwdVIRef)
IdToIndexMap[GVId].push_back(std::make_pair(Calls.size(), Loc));
Calls.push_back(FunctionSummary::EdgeTy{VI, CalleeInfo(Hotness, RelBF)});
@ -7895,7 +7904,7 @@ bool LLParser::ParseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls) {
// of any forward GV references that need updating later.
for (auto I : IdToIndexMap) {
for (auto P : I.second) {
assert(Calls[P.first].first == EmptyVI &&
assert(Calls[P.first].first.getRef() == FwdVIRef &&
"Forward referenced ValueInfo expected to be empty");
auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
I.first, std::vector<std::pair<ValueInfo *, LocTy>>()));
@ -7946,28 +7955,42 @@ bool LLParser::ParseOptionalRefs(std::vector<ValueInfo> &Refs) {
ParseToken(lltok::lparen, "expected '(' in refs"))
return true;
IdToIndexMapType IdToIndexMap;
struct ValueContext {
ValueInfo VI;
unsigned GVId;
LocTy Loc;
};
std::vector<ValueContext> VContexts;
// Parse each ref edge
do {
ValueInfo VI;
LocTy Loc = Lex.getLoc();
unsigned GVId;
if (ParseGVReference(VI, GVId))
ValueContext VC;
VC.Loc = Lex.getLoc();
if (ParseGVReference(VC.VI, VC.GVId))
return true;
VContexts.push_back(VC);
} while (EatIfPresent(lltok::comma));
// Sort value contexts so that ones with readonly ValueInfo are at the end
// of VContexts vector. This is needed to match immutableRefCount() behavior.
llvm::sort(VContexts, [](ValueContext &VC1, ValueContext &VC2) {
return VC1.VI.isReadOnly() < VC2.VI.isReadOnly();
});
IdToIndexMapType IdToIndexMap;
for (auto &VC : VContexts) {
// Keep track of the Refs array index needing a forward reference.
// We will save the location of the ValueInfo needing an update, but
// can only do so once the std::vector is finalized.
if (VI == EmptyVI)
IdToIndexMap[GVId].push_back(std::make_pair(Refs.size(), Loc));
Refs.push_back(VI);
} while (EatIfPresent(lltok::comma));
if (VC.VI.getRef() == FwdVIRef)
IdToIndexMap[VC.GVId].push_back(std::make_pair(Refs.size(), VC.Loc));
Refs.push_back(VC.VI);
}
// Now that the Refs vector is finalized, it is safe to save the locations
// of any forward GV references that need updating later.
for (auto I : IdToIndexMap) {
for (auto P : I.second) {
assert(Refs[P.first] == EmptyVI &&
assert(Refs[P.first].getRef() == FwdVIRef &&
"Forward referenced ValueInfo expected to be empty");
auto FwdRef = ForwardRefValueInfos.insert(std::make_pair(
I.first, std::vector<std::pair<ValueInfo *, LocTy>>()));
@ -8253,6 +8276,27 @@ bool LLParser::ParseGVFlags(GlobalValueSummary::GVFlags &GVFlags) {
return false;
}
/// GVarFlags
/// ::= 'varFlags' ':' '(' 'readonly' ':' Flag ')'
bool LLParser::ParseGVarFlags(GlobalVarSummary::GVarFlags &GVarFlags) {
assert(Lex.getKind() == lltok::kw_varFlags);
Lex.Lex();
unsigned Flag;
if (ParseToken(lltok::colon, "expected ':' here") ||
ParseToken(lltok::lparen, "expected '(' here") ||
ParseToken(lltok::kw_readonly, "expected 'readonly' here") ||
ParseToken(lltok::colon, "expected ':' here"))
return true;
ParseFlag(Flag);
GVarFlags.ReadOnly = Flag;
if (ParseToken(lltok::rparen, "expected ')' here"))
return true;
return false;
}
/// ModuleReference
/// ::= 'module' ':' UInt
bool LLParser::ParseModuleReference(StringRef &ModulePath) {
@ -8273,18 +8317,20 @@ bool LLParser::ParseModuleReference(StringRef &ModulePath) {
/// GVReference
/// ::= SummaryID
bool LLParser::ParseGVReference(ValueInfo &VI, unsigned &GVId) {
bool ReadOnly = EatIfPresent(lltok::kw_readonly);
if (ParseToken(lltok::SummaryID, "expected GV ID"))
return true;
GVId = Lex.getUIntVal();
// Check if we already have a VI for this GV
if (GVId < NumberedValueInfos.size()) {
assert(NumberedValueInfos[GVId] != EmptyVI);
assert(NumberedValueInfos[GVId].getRef() != FwdVIRef);
VI = NumberedValueInfos[GVId];
} else
// We will create a forward reference to the stored location.
VI = EmptyVI;
VI = ValueInfo(false, FwdVIRef);
if (ReadOnly)
VI.setReadOnly();
return false;
}

View File

@ -352,6 +352,7 @@ namespace llvm {
bool ParseVariableSummary(std::string Name, GlobalValue::GUID, unsigned ID);
bool ParseAliasSummary(std::string Name, GlobalValue::GUID, unsigned ID);
bool ParseGVFlags(GlobalValueSummary::GVFlags &GVFlags);
bool ParseGVarFlags(GlobalVarSummary::GVarFlags &GVarFlags);
bool ParseOptionalFFlags(FunctionSummary::FFlags &FFlags);
bool ParseOptionalCalls(std::vector<FunctionSummary::EdgeTy> &Calls);
bool ParseHotness(CalleeInfo::HotnessType &Hotness);

View File

@ -418,6 +418,7 @@ enum Kind {
kw_info,
kw_byte,
kw_bit,
kw_varFlags,
// Unsigned Valued tokens (UIntVal).
GlobalID, // @42

View File

@ -2821,7 +2821,7 @@ void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
}
void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
// Nothing for now
Out << ", varFlags: (readonly: " << GS->VarFlags.ReadOnly << ")";
}
static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
@ -3015,6 +3015,8 @@ void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) {
FieldSeparator FS;
for (auto &Ref : RefList) {
Out << FS;
if (Ref.isReadOnly())
Out << "readonly ";
Out << "^" << Machine.getGUIDSlot(Ref.getGUID());
}
Out << ")";

View File

@ -9,7 +9,7 @@
; Check a function that makes several calls with various profile hotness, and a
; reference (also tests forward references to function and variables in calls
; and refs).
^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none)), refs: (^13))))
^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none)), refs: (readonly ^13, ^14))))
; Function with a call that has relative block frequency instead of profile
; hotness.
@ -24,16 +24,16 @@
^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0))))
^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0))))
; Test appending globel variable with reference (tests backward reference on
; refs).
^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0), refs: (^4))))
^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0), refs: (^4))))
; Test a referenced global variable.
^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0))))
^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 1))))
; Test a dsoLocal variable.
^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1))))
^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1), varFlags: (readonly: 0))))
; Functions with various flag combinations (notEligibleToImport, Live,
; combinations of optional function flags).
@ -67,7 +67,7 @@
; Make sure we get back from llvm-dis essentially what we put in via llvm-as.
; CHECK: ^0 = module: (path: "thinlto-summary1.o", hash: (1369602428, 2747878711, 259090915, 2507395659, 1141468049))
; CHECK: ^1 = module: (path: "thinlto-summary2.o", hash: (2998369023, 4283347029, 1195487472, 2757298015, 1852134156))
; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none)), refs: (^13))))
; CHECK: ^2 = gv: (guid: 1, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15, hotness: hot), (callee: ^17, hotness: cold), (callee: ^16, hotness: none)), refs: (^14, readonly ^13))))
; CHECK: ^3 = gv: (guid: 2, summaries: (function: (module: ^1, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 10, calls: ((callee: ^15)))))
; CHECK: ^4 = gv: (guid: 3, summaries: (function: (module: ^0, flags: (linkage: internal, notEligibleToImport: 0, live: 0, dsoLocal: 1), insts: 1)))
; CHECK: ^5 = gv: (guid: 4, summaries: (alias: (module: ^0, flags: (linkage: private, notEligibleToImport: 0, live: 0, dsoLocal: 1), aliasee: ^14)))
@ -76,10 +76,10 @@
; CHECK: ^8 = gv: (guid: 7, summaries: (function: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
; CHECK: ^9 = gv: (guid: 8, summaries: (function: (module: ^0, flags: (linkage: weak_odr, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
; CHECK: ^10 = gv: (guid: 9, summaries: (function: (module: ^0, flags: (linkage: weak, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 1)))
; CHECK: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0))))
; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0), refs: (^4))))
; 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: ^11 = gv: (guid: 10, summaries: (variable: (module: ^0, flags: (linkage: common, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0))))
; CHECK: ^12 = gv: (guid: 11, summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 0), refs: (^4))))
; CHECK: ^13 = gv: (guid: 12, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 1))))
; CHECK: ^14 = gv: (guid: 13, summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 1), varFlags: (readonly: 0))))
; 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, 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, noInline: 0), calls: ((callee: ^15)))))

View File

@ -38,5 +38,5 @@ declare void @func(...) #1
; DIS: ^0 = module: (path: "{{.*}}", hash: (0, 0, 0, 0, 0))
; DIS: ^1 = gv: (name: "func") ; guid = 7289175272376759421
; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 3, calls: ((callee: ^1, relbf: 256)), refs: (^3)))) ; guid = 15822663052811949562
; DIS: ^2 = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 3, calls: ((callee: ^1, relbf: 256)), refs: (readonly ^3)))) ; guid = 15822663052811949562
; DIS: ^3 = gv: (name: "undefinedglob") ; guid = 18036901804029949403

View File

@ -154,11 +154,11 @@ entry:
; DIS-DAG: = gv: (name: "foo") ; guid = 6699318081062747564
; DIS-DAG: = gv: (name: "func") ; guid = 7289175272376759421
; DIS-DAG: = gv: (name: "func3") ; guid = 11517462787082255043
; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0)))) ; guid = 12887606300320728018
; DIS-DAG: = gv: (name: "globalvar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 1)))) ; guid = 12887606300320728018
; DIS-DAG: = gv: (name: "func2") ; guid = 14069196320850861797
; DIS-DAG: = gv: (name: "llvm.ctpop.i8") ; guid = 15254915475081819833
; DIS-DAG: = gv: (name: "main", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 9, calls: ((callee: ^{{.*}})), refs: (^{{.*}})))) ; guid = 15822663052811949562
; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), refs: (^{{.*}})))) ; guid = 16434608426314478903
; DIS-DAG: = gv: (name: "bar", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), varFlags: (readonly: 1), refs: (^{{.*}})))) ; guid = 16434608426314478903
; Don't try to match the exact GUID. Since it is private, the file path
; will get hashed, and that will be test dependent.
; DIS-DAG: = gv: (name: "Y", summaries: (function: (module: ^0, flags: (linkage: private, notEligibleToImport: 0, live: 0, dsoLocal: 1), insts: 14, calls: ((callee: ^{{.*}}))))) ; guid =