diff options
| author | Teresa Johnson <tejohnson@google.com> | 2019-01-17 15:49:03 +0000 | 
|---|---|---|
| committer | Teresa Johnson <tejohnson@google.com> | 2019-01-17 15:49:03 +0000 | 
| commit | 4fcf3b16212481f7debebb1f35681cff8cdf81ea (patch) | |
| tree | e783c9fe4ee7c2682b4d6f77a854b3494442c95b /llvm/lib/AsmParser | |
| parent | e50d9cb3649bdf6521f92fd1e4cee3a690638159 (diff) | |
| download | bcm5719-llvm-4fcf3b16212481f7debebb1f35681cff8cdf81ea.tar.gz bcm5719-llvm-4fcf3b16212481f7debebb1f35681cff8cdf81ea.zip  | |
[ThinLTO] Add summary entries for index-based WPD
Summary:
If LTOUnit splitting is disabled, the module summary analysis computes
the summary information necessary to perform single implementation
devirtualization during the thin link with the index and no IR. The
information collected from the regular LTO IR in the current hybrid WPD
algorithm is summarized, including:
1) For vtable definitions, record the function pointers and their offset
within the vtable initializer (subsumes the information collected from
IR by tryFindVirtualCallTargets).
2) A record for each type metadata summarizing the vtable definitions
decorated with that metadata (subsumes the TypeIdentiferMap collected
from IR).
Also added are the necessary bitcode records, and the corresponding
assembly support.
The index-based WPD will be sent as a follow-on.
Depends on D53890.
Reviewers: pcc
Subscribers: mehdi_amini, Prazek, inglorion, eraman, steven_wu, dexonsmith, arphaman, llvm-commits
Differential Revision: https://reviews.llvm.org/D54815
llvm-svn: 351453
Diffstat (limited to 'llvm/lib/AsmParser')
| -rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 168 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 2 | ||||
| -rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 3 | 
4 files changed, 172 insertions, 4 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index eab7ec81953..f5246d5480b 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -749,6 +749,8 @@ lltok::Kind LLLexer::LexIdentifier() {    KEYWORD(critical);    KEYWORD(relbf);    KEYWORD(variable); +  KEYWORD(vTableFuncs); +  KEYWORD(virtFunc);    KEYWORD(aliasee);    KEYWORD(refs);    KEYWORD(typeIdInfo); @@ -761,6 +763,7 @@ lltok::Kind LLLexer::LexIdentifier() {    KEYWORD(offset);    KEYWORD(args);    KEYWORD(typeid); +  KEYWORD(typeidMetadata);    KEYWORD(summary);    KEYWORD(typeTestRes);    KEYWORD(kind); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 816bb4e9401..5ef171fe965 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -822,6 +822,9 @@ bool LLParser::ParseSummaryEntry() {    case lltok::kw_typeid:      return ParseTypeIdEntry(SummaryID);      break; +  case lltok::kw_typeidMetadata: +    return ParseTypeIdMetadataEntry(SummaryID); +    break;    default:      return Error(Lex.getLoc(), "unexpected summary kind");    } @@ -7257,6 +7260,90 @@ bool LLParser::ParseTypeIdSummary(TypeIdSummary &TIS) {    return false;  } +static ValueInfo EmptyVI = +    ValueInfo(false, (GlobalValueSummaryMapTy::value_type *)-8); + +/// TypeIdMetadataEntry +///   ::= 'typeidMetadata' ':' '(' 'name' ':' STRINGCONSTANT ',' TypeIdGVInfo +///   ')' +bool LLParser::ParseTypeIdMetadataEntry(unsigned ID) { +  assert(Lex.getKind() == lltok::kw_typeidMetadata); +  Lex.Lex(); + +  std::string Name; +  if (ParseToken(lltok::colon, "expected ':' here") || +      ParseToken(lltok::lparen, "expected '(' here") || +      ParseToken(lltok::kw_name, "expected 'name' here") || +      ParseToken(lltok::colon, "expected ':' here") || +      ParseStringConstant(Name)) +    return true; + +  TypeIdGVInfo &TI = Index->getOrInsertTypeIdMetadataSummary(Name); +  if (ParseToken(lltok::comma, "expected ',' here") || +      ParseToken(lltok::kw_summary, "expected 'summary' here") || +      ParseToken(lltok::colon, "expected ':' here") || +      ParseToken(lltok::lparen, "expected '(' here")) +    return true; + +  IdToIndexMapType IdToIndexMap; +  // Parse each call edge +  do { +    uint64_t Offset; +    if (ParseToken(lltok::lparen, "expected '(' here") || +        ParseToken(lltok::kw_offset, "expected 'offset' here") || +        ParseToken(lltok::colon, "expected ':' here") || ParseUInt64(Offset) || +        ParseToken(lltok::comma, "expected ',' here")) +      return true; + +    LocTy Loc = Lex.getLoc(); +    unsigned GVId; +    ValueInfo VI; +    if (ParseGVReference(VI, GVId)) +      return true; + +    // Keep track of the TypeIdGVInfo 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(TI.size(), Loc)); +    TI.push_back({Offset, VI}); + +    if (ParseToken(lltok::rparen, "expected ')' in call")) +      return true; +  } while (EatIfPresent(lltok::comma)); + +  // Now that the TI 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(TI[P.first].second == EmptyVI && +             "Forward referenced ValueInfo expected to be empty"); +      auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( +          I.first, std::vector<std::pair<ValueInfo *, LocTy>>())); +      FwdRef.first->second.push_back( +          std::make_pair(&TI[P.first].second, P.second)); +    } +  } + +  if (ParseToken(lltok::rparen, "expected ')' here") || +      ParseToken(lltok::rparen, "expected ')' here")) +    return true; + +  // Check if this ID was forward referenced, and if so, update the +  // corresponding GUIDs. +  auto FwdRefTIDs = ForwardRefTypeIds.find(ID); +  if (FwdRefTIDs != ForwardRefTypeIds.end()) { +    for (auto TIDRef : FwdRefTIDs->second) { +      assert(!*TIDRef.first && +             "Forward referenced type id GUID expected to be 0"); +      *TIDRef.first = GlobalValue::getGUID(Name); +    } +    ForwardRefTypeIds.erase(FwdRefTIDs); +  } + +  return false; +} +  /// TypeTestResolution  ///   ::= 'typeTestRes' ':' '(' 'kind' ':'  ///         ( 'unsat' | 'byteArray' | 'inline' | 'single' | 'allOnes' ) ',' @@ -7764,6 +7851,7 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,        /*Live=*/false, /*IsLocal=*/false);    GlobalVarSummary::GVarFlags GVarFlags(/*ReadOnly*/ false);    std::vector<ValueInfo> Refs; +  VTableFuncList VTableFuncs;    if (ParseToken(lltok::colon, "expected ':' here") ||        ParseToken(lltok::lparen, "expected '(' here") ||        ParseModuleReference(ModulePath) || @@ -7772,10 +7860,20 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,        ParseGVarFlags(GVarFlags))      return true; -  // Parse optional refs field -  if (EatIfPresent(lltok::comma)) { -    if (ParseOptionalRefs(Refs)) -      return true; +  // Parse optional fields +  while (EatIfPresent(lltok::comma)) { +    switch (Lex.getKind()) { +    case lltok::kw_vTableFuncs: +      if (ParseOptionalVTableFuncs(VTableFuncs)) +        return true; +      break; +    case lltok::kw_refs: +      if (ParseOptionalRefs(Refs)) +        return true; +      break; +    default: +      return Error(Lex.getLoc(), "expected optional variable summary field"); +    }    }    if (ParseToken(lltok::rparen, "expected ')' here")) @@ -7785,6 +7883,7 @@ bool LLParser::ParseVariableSummary(std::string Name, GlobalValue::GUID GUID,        llvm::make_unique<GlobalVarSummary>(GVFlags, GVarFlags, std::move(Refs));    GS->setModulePath(ModulePath); +  GS->setVTableFuncs(std::move(VTableFuncs));    AddGlobalValueToIndex(Name, GUID, (GlobalValue::LinkageTypes)GVFlags.Linkage,                          ID, std::move(GS)); @@ -8002,6 +8101,67 @@ bool LLParser::ParseHotness(CalleeInfo::HotnessType &Hotness) {    return false;  } +/// OptionalVTableFuncs +///   := 'vTableFuncs' ':' '(' VTableFunc [',' VTableFunc]* ')' +/// VTableFunc ::= '(' 'virtFunc' ':' GVReference ',' 'offset' ':' UInt64 ')' +bool LLParser::ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs) { +  assert(Lex.getKind() == lltok::kw_vTableFuncs); +  Lex.Lex(); + +  if (ParseToken(lltok::colon, "expected ':' in vTableFuncs") | +      ParseToken(lltok::lparen, "expected '(' in vTableFuncs")) +    return true; + +  IdToIndexMapType IdToIndexMap; +  // Parse each virtual function pair +  do { +    ValueInfo VI; +    if (ParseToken(lltok::lparen, "expected '(' in vTableFunc") || +        ParseToken(lltok::kw_virtFunc, "expected 'callee' in vTableFunc") || +        ParseToken(lltok::colon, "expected ':'")) +      return true; + +    LocTy Loc = Lex.getLoc(); +    unsigned GVId; +    if (ParseGVReference(VI, GVId)) +      return true; + +    uint64_t Offset; +    if (ParseToken(lltok::comma, "expected comma") || +        ParseToken(lltok::kw_offset, "expected offset") || +        ParseToken(lltok::colon, "expected ':'") || ParseUInt64(Offset)) +      return true; + +    // Keep track of the VTableFuncs 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(VTableFuncs.size(), Loc)); +    VTableFuncs.push_back(std::make_pair(VI, Offset)); + +    if (ParseToken(lltok::rparen, "expected ')' in vTableFunc")) +      return true; +  } while (EatIfPresent(lltok::comma)); + +  // Now that the VTableFuncs 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(VTableFuncs[P.first].first == EmptyVI && +             "Forward referenced ValueInfo expected to be empty"); +      auto FwdRef = ForwardRefValueInfos.insert(std::make_pair( +          I.first, std::vector<std::pair<ValueInfo *, LocTy>>())); +      FwdRef.first->second.push_back( +          std::make_pair(&VTableFuncs[P.first].first, P.second)); +    } +  } + +  if (ParseToken(lltok::rparen, "expected ')' in vTableFuncs")) +    return true; + +  return false; +} +  /// OptionalRefs  ///   := 'refs' ':' '(' GVReference [',' GVReference]* ')'  bool LLParser::ParseOptionalRefs(std::vector<ValueInfo> &Refs) { diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index 5a0fc297265..272f1ac68a8 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -369,9 +369,11 @@ namespace llvm {                           IdToIndexMapType &IdToIndexMap, unsigned Index);      bool ParseVFuncId(FunctionSummary::VFuncId &VFuncId,                        IdToIndexMapType &IdToIndexMap, unsigned Index); +    bool ParseOptionalVTableFuncs(VTableFuncList &VTableFuncs);      bool ParseOptionalRefs(std::vector<ValueInfo> &Refs);      bool ParseTypeIdEntry(unsigned ID);      bool ParseTypeIdSummary(TypeIdSummary &TIS); +    bool ParseTypeIdMetadataEntry(unsigned ID);      bool ParseTypeTestResolution(TypeTestResolution &TTRes);      bool ParseOptionalWpdResolutions(          std::map<uint64_t, WholeProgramDevirtResolution> &WPDResMap); diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index c2e2795a946..13e574241a0 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -379,6 +379,8 @@ enum Kind {    kw_critical,    kw_relbf,    kw_variable, +  kw_vTableFuncs, +  kw_virtFunc,    kw_aliasee,    kw_refs,    kw_typeIdInfo, @@ -391,6 +393,7 @@ enum Kind {    kw_offset,    kw_args,    kw_typeid, +  kw_typeidMetadata,    kw_summary,    kw_typeTestRes,    kw_kind,  | 

