Ejemplo n.º 1
0
// Devirtualize and specialize a group of applies, returning a
// worklist of newly exposed function references that should be
// considered for inlining before continuing with the caller that has
// the passed-in applies.
//
// The returned worklist is stacked such that the last things we want
// to process are earlier on the list.
//
// Returns true if any changes were made.
bool SILPerformanceInliner::devirtualizeAndSpecializeApplies(
                                  llvm::SmallVectorImpl<ApplySite> &Applies,
                                  SILModuleTransform *MT,
                                  ClassHierarchyAnalysis *CHA,
                               llvm::SmallVectorImpl<SILFunction *> &WorkList) {
  assert(WorkList.empty() && "Expected empty worklist for return results!");

  bool ChangedAny = false;

  // The set of all new function references generated by
  // devirtualization and specialization.
  llvm::SetVector<SILFunction *> NewRefs;

  // Process all applies passed in, plus any new ones that are pushed
  // on as a result of specializing the referenced functions.
  while (!Applies.empty()) {
    auto Apply = Applies.back();
    Applies.pop_back();

    bool ChangedApply = false;
    if (auto FullApply = FullApplySite::isa(Apply.getInstruction())) {
      if (auto NewApply = devirtualize(FullApply, CHA)) {
        ChangedApply = true;

        Apply = ApplySite(NewApply.getInstruction());
      }
    }

    llvm::SmallVector<ApplySite, 4> NewApplies;
    if (auto NewApply = specializeGeneric(Apply, NewApplies)) {
      ChangedApply = true;

      Apply = NewApply;
      Applies.insert(Applies.end(), NewApplies.begin(), NewApplies.end());
    }

    if (ChangedApply) {
      ChangedAny = true;

      auto *NewCallee = Apply.getCalleeFunction();
      assert(NewCallee && "Expected directly referenced function!");

      // Track all new references to function definitions.
      if (NewCallee->isDefinition())
        NewRefs.insert(NewCallee);


      // TODO: Do we need to invalidate everything at this point?
      // What about side-effects analysis? What about type analysis?
      MT->invalidateAnalysis(Apply.getFunction(),
                             SILAnalysis::InvalidationKind::Everything);
    }
  }

  // Copy out all the new function references gathered.
  if (ChangedAny)
    WorkList.insert(WorkList.end(), NewRefs.begin(), NewRefs.end());

  return ChangedAny;
}
Ejemplo n.º 2
0
void UUID::toString(llvm::SmallVectorImpl<char> &out) const {
  out.resize(UUID::StringBufferSize);
  uuid_unparse_upper(Value, out.data());
  // Pop off the null terminator.
  assert(out.back() == '\0' && "did not null-terminate?!");
  out.pop_back();
}
Ejemplo n.º 3
0
/// Parse an identifier in an MS-style inline assembly block.
///
/// \param CastInfo - a void* so that we don't have to teach Parser.h
///   about the actual type.
ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
                                        unsigned &NumLineToksConsumed,
                                        void *CastInfo,
                                        bool IsUnevaluatedContext) {
  llvm::InlineAsmIdentifierInfo &Info =
      *(llvm::InlineAsmIdentifierInfo *)CastInfo;

  // Push a fake token on the end so that we don't overrun the token
  // stream.  We use ';' because it expression-parsing should never
  // overrun it.
  const tok::TokenKind EndOfStream = tok::semi;
  Token EndOfStreamTok;
  EndOfStreamTok.startToken();
  EndOfStreamTok.setKind(EndOfStream);
  LineToks.push_back(EndOfStreamTok);

  // Also copy the current token over.
  LineToks.push_back(Tok);

  PP.EnterTokenStream(LineToks.begin(), LineToks.size(),
                      /*disable macros*/ true,
                      /*owns tokens*/ false);

  // Clear the current token and advance to the first token in LineToks.
  ConsumeAnyToken();

  // Parse an optional scope-specifier if we're in C++.
  CXXScopeSpec SS;
  if (getLangOpts().CPlusPlus) {
    ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false);
  }

  // Require an identifier here.
  SourceLocation TemplateKWLoc;
  UnqualifiedId Id;
  bool Invalid = true;
  ExprResult Result;
  if (Tok.is(tok::kw_this)) {
    Result = ParseCXXThis();
    Invalid = false;
  } else {
    Invalid =
        ParseUnqualifiedId(SS,
                           /*EnteringContext=*/false,
                           /*AllowDestructorName=*/false,
                           /*AllowConstructorName=*/false,
                           /*ObjectType=*/ParsedType(), TemplateKWLoc, Id);
    // Perform the lookup.
    Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
                                               IsUnevaluatedContext);
  }
  // While the next two tokens are 'period' 'identifier', repeatedly parse it as
  // a field access. We have to avoid consuming assembler directives that look
  // like '.' 'else'.
  while (Result.isUsable() && Tok.is(tok::period)) {
    Token IdTok = PP.LookAhead(0);
    if (IdTok.isNot(tok::identifier))
      break;
    ConsumeToken(); // Consume the period.
    IdentifierInfo *Id = Tok.getIdentifierInfo();
    ConsumeToken(); // Consume the identifier.
    Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
                                                 Info, Tok.getLocation());
  }

  // Figure out how many tokens we are into LineToks.
  unsigned LineIndex = 0;
  if (Tok.is(EndOfStream)) {
    LineIndex = LineToks.size() - 2;
  } else {
    while (LineToks[LineIndex].getLocation() != Tok.getLocation()) {
      LineIndex++;
      assert(LineIndex < LineToks.size() - 2); // we added two extra tokens
    }
  }

  // If we've run into the poison token we inserted before, or there
  // was a parsing error, then claim the entire line.
  if (Invalid || Tok.is(EndOfStream)) {
    NumLineToksConsumed = LineToks.size() - 2;
  } else {
    // Otherwise, claim up to the start of the next token.
    NumLineToksConsumed = LineIndex;
  }

  // Finally, restore the old parsing state by consuming all the tokens we
  // staged before, implicitly killing off the token-lexer we pushed.
  for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) {
    ConsumeAnyToken();
  }
  assert(Tok.is(EndOfStream));
  ConsumeToken();

  // Leave LineToks in its original state.
  LineToks.pop_back();
  LineToks.pop_back();

  return Result;
}
Store BasicStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
        SymbolReaper& SymReaper,
        llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)
{
    BindingsTy B = GetBindings(store);
    typedef SVal::symbol_iterator symbol_iterator;

    // Iterate over the variable bindings.
    for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
        if (const VarRegion *VR = dyn_cast<VarRegion>(I.getKey())) {
            if (SymReaper.isLive(Loc, VR))
                RegionRoots.push_back(VR);
            else
                continue;
        }
        else if (isa<ObjCIvarRegion>(I.getKey())) {
            RegionRoots.push_back(I.getKey());
        }
        else
            continue;

        // Mark the bindings in the data as live.
        SVal X = I.getData();
        for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
            SymReaper.markLive(*SI);
    }

    // Scan for live variables and live symbols.
    llvm::SmallPtrSet<const MemRegion*, 10> Marked;

    while (!RegionRoots.empty()) {
        const MemRegion* MR = RegionRoots.back();
        RegionRoots.pop_back();

        while (MR) {
            if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(MR)) {
                SymReaper.markLive(SymR->getSymbol());
                break;
            }
            else if (isa<VarRegion>(MR) || isa<ObjCIvarRegion>(MR)) {
                if (Marked.count(MR))
                    break;

                Marked.insert(MR);
                SVal X = Retrieve(store, loc::MemRegionVal(MR));

                // FIXME: We need to handle symbols nested in region definitions.
                for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end(); SI!=SE; ++SI)
                    SymReaper.markLive(*SI);

                if (!isa<loc::MemRegionVal>(X))
                    break;

                const loc::MemRegionVal& LVD = cast<loc::MemRegionVal>(X);
                RegionRoots.push_back(LVD.getRegion());
                break;
            }
            else if (const SubRegion* R = dyn_cast<SubRegion>(MR))
                MR = R->getSuperRegion();
            else
                break;
        }
    }

    // Remove dead variable bindings.
    for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
        const MemRegion* R = I.getKey();

        if (!Marked.count(R)) {
            store = Remove(store, ValMgr.makeLoc(R));
            SVal X = I.getData();

            for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
                SymReaper.maybeDead(*SI);
        }
    }

    return store;
}