Repository: apple/swift
File: lib/IRGen/MetadataRequest.cpp (C++)

Code before:
  case 3: {
    if (!flags.hasParameterFlags() && !type->isDifferentiable() &&
        !type->getGlobalActor() && !hasPackExpansion &&
        !flags.hasExtendedFlags()) {
      llvm::SmallVector<llvm::Value *, 8> arguments;
      auto metadataFn = constructSimpleCall(arguments);
      auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
      call->setDoesNotThrow();
      return MetadataResponse::forComplete(call);
    }

    // If function type has parameter flags or is differentiable or has a
    // global actor, emit the most general function to retrieve them.
    LLVM_FALLTHROUGH;
  }

  default:
    llvm::SmallVector<llvm::Value *, 8> arguments;

    llvm::SmallVector<llvm::Value *, 8> backdeployArgs;
    bool isBackDeployingNonisolatedNonSendingFn =
        flags.hasExtendedFlags() &&
        (extFlags == decltype(extFlags)().withNonIsolatedCaller()) &&
        !type->isDifferentiable() &&
        cast<llvm::Function>(IGF.IGM.getGetFunctionMetadataExtendedFn())
            ->hasExternalWeakLinkage();

    arguments.push_back(flagsVal);
    if (isBackDeployingNonisolatedNonSendingFn)
      backdeployArgs.push_back(flagsVal);

    llvm::Value *diffKindVal = nullptr;

    {
      FunctionMetadataDifferentiabilityKind metadataDifferentiabilityKind;
      switch (type->getDifferentiabilityKind()) {
      case DifferentiabilityKind::NonDifferentiable:
        metadataDifferentiabilityKind =
            FunctionMetadataDifferentiabilityKind::NonDifferentiable;
        break;
      case DifferentiabilityKind::Normal:
        metadataDifferentiabilityKind =
            FunctionMetadataDifferentiabilityKind::Normal;
        break;
      case DifferentiabilityKind::Linear:
        metadataDifferentiabilityKind =
            FunctionMetadataDifferentiabilityKind::Linear;
        break;
      case DifferentiabilityKind::Forward:
        metadataDifferentiabilityKind =
            FunctionMetadataDifferentiabilityKind::Forward;

Review comment (performance):
Can we just unconditionally call a helper function that does this deployment check and then calls one of the runtime functions? That would add less combinatorial complexity to this function.

Code after:
  auto result =
    IGF.emitAbstractTypeMetadataRef(type->getResult()->getCanonicalType());

  auto params = type.getParams();
  bool hasPackExpansion = type->containsPackExpansionParam();

  FunctionTypeFlags flags;
  ExtendedFunctionTypeFlags extFlags;

  std::tie(flags, extFlags) = getFunctionTypeFlags(type);
  llvm::Value *flagsVal = nullptr;
  llvm::Value *shapeExpression = nullptr;
  CanPackType packType;

  if (!hasPackExpansion) {
    flags = flags.withNumParameters(params.size());
    flagsVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
                                      flags.getIntValue());
  } else {
    packType = getInducedPackType(type.getParams(), type->getASTContext());
    auto *shapeExpression = IGF.emitPackShapeExpression(packType);

    flagsVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
                                      flags.getIntValue());
    flagsVal = IGF.Builder.CreateOr(flagsVal, shapeExpression);
  }

  auto constructSimpleCall =
      [&](llvm::SmallVectorImpl<llvm::Value *> &arguments)
      -> FunctionPointer {
    assert(!flags.hasParameterFlags());
    assert(!shapeExpression);

    arguments.push_back(flagsVal);

    for (auto param : params) {
      arguments.push_back(getFunctionParameterRef(IGF, param));
    }

    arguments.push_back(result);

    switch (params.size()) {
    case 0:
      return IGF.IGM.getGetFunctionMetadata0FunctionPointer();

    case 1:
      return IGF.IGM.getGetFunctionMetadata1FunctionPointer();

    case 2:
      return IGF.IGM.getGetFunctionMetadata2FunctionPointer();