示例#1
0
ApplySite SILPerformanceInliner::specializeGeneric(
    ApplySite Apply, llvm::SmallVectorImpl<ApplySite> &NewApplies) {
  assert(NewApplies.empty() && "Expected out parameter for new applies!");

  if (!Apply.hasSubstitutions())
    return ApplySite();

  auto *Callee = Apply.getCalleeFunction();

  if (!Callee || Callee->isExternalDeclaration())
    return ApplySite();

  auto Filter = [](SILInstruction *I) -> bool {
    return ApplySite::isa(I) != ApplySite();
  };

  CloneCollector Collector(Filter);

  SILFunction *SpecializedFunction;
  auto Specialized = trySpecializeApplyOfGeneric(Apply,
                                                 SpecializedFunction,
                                                 Collector);

  if (!Specialized)
    return ApplySite();

  // Track the new applies from the specialization.
  for (auto NewCallSite : Collector.getInstructionPairs())
    NewApplies.push_back(ApplySite(NewCallSite.first));

  auto FullApply = FullApplySite::isa(Apply.getInstruction());

  if (!FullApply) {
    assert(!FullApplySite::isa(Specialized.getInstruction()) &&
           "Unexpected full apply generated!");

    // Replace the old apply with the new and delete the old.
    replaceDeadApply(Apply, Specialized.getInstruction());

    return ApplySite(Specialized);
  }

  // Replace the old apply with the new and delete the old.
  replaceDeadApply(Apply, Specialized.getInstruction());

  return Specialized;
}
/// For each argument in the range of the callee arguments being applied at the
/// given apply site, use the summary analysis to determine whether the
/// arguments will be accessed in a way that conflicts with any currently in
/// progress accesses. If so, diagnose.
static void checkCaptureAccess(ApplySite Apply, AccessState &State) {
  SILFunction *Callee = Apply.getCalleeFunction();
  if (!Callee || Callee->empty())
    return;

  const AccessSummaryAnalysis::FunctionSummary &FS =
      State.ASA->getOrCreateSummary(Callee);

  for (unsigned ArgumentIndex : range(Apply.getNumArguments())) {

    unsigned CalleeIndex =
        Apply.getCalleeArgIndexOfFirstAppliedArg() + ArgumentIndex;

    const AccessSummaryAnalysis::ArgumentSummary &AS =
        FS.getAccessForArgument(CalleeIndex);

    const auto &SubAccesses = AS.getSubAccesses();

    // Is the capture accessed in the callee?
    if (SubAccesses.empty())
      continue;

    SILValue Argument = Apply.getArgument(ArgumentIndex);
    assert(Argument->getType().isAddress());

    // A valid AccessedStorage should alway sbe found because Unsafe accesses
    // are not tracked by AccessSummaryAnalysis.
    const AccessedStorage &Storage = findValidAccessedStorage(Argument);
    auto AccessIt = State.Accesses->find(Storage);

    // Are there any accesses in progress at the time of the call?
    if (AccessIt == State.Accesses->end())
      continue;

    const AccessInfo &Info = AccessIt->getSecond();
    if (auto Conflict = findConflictingArgumentAccess(AS, Storage, Info))
      State.ConflictingAccesses.push_back(*Conflict);
  }
}
示例#3
0
bool GenericSpecializer::specializeAppliesInFunction(SILFunction &F) {
  bool Changed = false;
  llvm::SmallVector<SILInstruction *, 8> DeadApplies;

  for (auto &BB : F) {
    for (auto It = BB.begin(), End = BB.end(); It != End;) {
      auto &I = *It++;

      // Skip non-apply instructions, apply instructions with no
      // substitutions, apply instructions where we do not statically
      // know the called function, and apply instructions where we do
      // not have the body of the called function.

      ApplySite Apply = ApplySite::isa(&I);
      if (!Apply || !Apply.hasSubstitutions())
        continue;

      auto *Callee = Apply.getCalleeFunction();
      if (!Callee || !Callee->isDefinition())
        continue;

      // We have a call that can potentially be specialized, so
      // attempt to do so.

      // The specializer helper function currently expects a collector
      // argument, but we aren't going to make use of the results so
      // we'll have our filter always return false;
      auto Filter = [](SILInstruction *I) -> bool { return false; };
      CloneCollector Collector(Filter);

      SILFunction *SpecializedFunction;

      auto Specialized =
          trySpecializeApplyOfGeneric(Apply, SpecializedFunction, Collector);

      if (Specialized) {
        Changed = true;

        // If calling the specialization utility resulted in a new
        // function (as opposed to returning a previous
        // specialization), we need to notify the pass manager so that
        // the new function gets optimized.
        if (SpecializedFunction)
          notifyPassManagerOfFunction(SpecializedFunction);

        auto *AI = Apply.getInstruction();

        if (!isa<TryApplyInst>(AI))
          AI->replaceAllUsesWith(Specialized.getInstruction());

        DeadApplies.push_back(AI);
      }
    }
  }

  // Remove all the now-dead applies.
  while (!DeadApplies.empty()) {
    auto *AI = DeadApplies.pop_back_val();
    recursivelyDeleteTriviallyDeadInstructions(AI, true);
  }

  return Changed;
}