<commit_before>//===--- FunctionSignatureOpts.h --------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SILOPTIMIZER_TRANSFORMS_FUNCTIONSIGNATUREOPTS_H
#define SWIFT_SILOPTIMIZER_TRANSFORMS_FUNCTIONSIGNATUREOPTS_H

#include "swift/Basic/LLVM.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/Analysis/CallerAnalysis.h"
#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "llvm/ADT/DenseMap.h"

namespace swift {

/// A structure that maintains all of the information about a specific
/// SILArgument that we are tracking.
struct ArgumentDescriptor {
  /// The argument that we are tracking original data for.
  SILFunctionArgument *Arg;

  /// Parameter Info.
  Optional<SILParameterInfo> PInfo;

  /// The original index of this argument.
  unsigned Index;

  /// The original decl of this Argument.
  const ValueDecl *Decl;

  /// Was this parameter originally dead?
  bool IsEntirelyDead;

  /// Was this argument completely removed already?
  ///
  /// TODO: Could we make ArgumentDescriptors just optional and once they have
  /// been consumed no longer process them?
  bool WasErased;

  /// Should the argument be exploded ?
  bool Explode;

  /// This parameter is owned to guaranteed.
  bool OwnedToGuaranteed;

  /// Is this parameter an indirect result?
  bool IsIndirectResult;

  /// If non-empty, this is the set of releases in the return block of
  /// the callee associated with this parameter if it is @owned. If it
  /// is empty then we could not find any such releases.
  TinyPtrVector<SILInstruction *> CalleeRelease;

  /// The same as CalleeRelease, but the releases are post-dominated
  /// by the throw block, if it is a function which has a throw block.
  TinyPtrVector<SILInstruction *> CalleeReleaseInThrowBlock;

  /// The projection tree of this arguments.
  ProjectionTree ProjTree;

  ArgumentDescriptor() = delete;

  /// Initialize this argument descriptor with all information from A that we
  /// use in our optimization.
  ///
  /// *NOTE* We cache a lot of data from the argument and maintain a reference
  /// to the original argument. The reason why we do this is to make sure we
  /// have access to the original argument's state if we modify the argument
  /// when optimizing.
  ArgumentDescriptor(
      SILFunctionArgument *A,
      llvm::SpecificBumpPtrAllocator<ProjectionTreeNode> &Allocator)
      : Arg(A), PInfo(A->getKnownParameterInfo()), Index(A->getIndex()),
        Decl(A->getDecl()), IsEntirelyDead(false), WasErased(false),
        Explode(false), OwnedToGuaranteed(false),
        IsIndirectResult(A->isIndirectResult()), CalleeRelease(),
        CalleeReleaseInThrowBlock(),
        ProjTree(A->getModule(), A->getType(), Allocator) {
    if (!A->isIndirectResult()) {
      PInfo = Arg->getKnownParameterInfo();
    }
  }

  ArgumentDescriptor(const ArgumentDescriptor &) = delete;
  ArgumentDescriptor(ArgumentDescriptor &&) = default;
  ArgumentDescriptor &operator=(const ArgumentDescriptor &) = delete;
  ArgumentDescriptor &operator=(ArgumentDescriptor &&) = default;

  /// \returns true if this argument's convention is P.
  bool hasConvention(SILArgumentConvention P) const {
    return Arg->hasConvention(P);
  }

  bool canOptimizeLiveArg() const {
    if (Arg->getType().isObject())
      return true;
    // @in arguments of generic types can be processed.
    if (Arg->getType().hasArchetype() &&
        Arg->getType().isAddress() &&
        (Arg->hasConvention(SILArgumentConvention::Indirect_In) ||
         Arg->hasConvention(SILArgumentConvention::Indirect_In_Guaranteed)))
      return true;
    return false;
  }

  llvm::Optional<ValueOwnershipKind>
  getTransformedOwnershipKind(SILType SubTy) {
    if (IsEntirelyDead)
      return None;
    if (SubTy.isTrivial(*Arg->getFunction()))
      return Optional<ValueOwnershipKind>(ValueOwnershipKind::Any);
    if (OwnedToGuaranteed)
      return Optional<ValueOwnershipKind>(ValueOwnershipKind::Guaranteed);
    return Arg->getOwnershipKind();
  }
};

/// A structure that maintains all of the information about a specific
/// direct result that we are tracking.
struct ResultDescriptor {
  /// The original parameter info of this argument.
  SILResultInfo ResultInfo;<commit_msg>[Gardening] Documented ArgumentDescriptor method.<commit_after>//===--- FunctionSignatureOpts.h --------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SILOPTIMIZER_TRANSFORMS_FUNCTIONSIGNATUREOPTS_H
#define SWIFT_SILOPTIMIZER_TRANSFORMS_FUNCTIONSIGNATUREOPTS_H

#include "swift/Basic/LLVM.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
#include "swift/SILOptimizer/Analysis/AliasAnalysis.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
#include "swift/SILOptimizer/Analysis/CallerAnalysis.h"
#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "llvm/ADT/DenseMap.h"

namespace swift {

/// A structure that maintains all of the information about a specific
/// SILArgument that we are tracking.
struct ArgumentDescriptor {
  /// The argument that we are tracking original data for.
  SILFunctionArgument *Arg;

  /// Parameter Info.
  Optional<SILParameterInfo> PInfo;

  /// The original index of this argument.
  unsigned Index;

  /// The original decl of this Argument.
  const ValueDecl *Decl;

  /// Was this parameter originally dead?
  bool IsEntirelyDead;

  /// Was this argument completely removed already?
  ///
  /// TODO: Could we make ArgumentDescriptors just optional and once they have
  /// been consumed no longer process them?
  bool WasErased;

  /// Should the argument be exploded ?
  bool Explode;

  /// This parameter is owned to guaranteed.
  bool OwnedToGuaranteed;

  /// Is this parameter an indirect result?
  bool IsIndirectResult;

  /// If non-empty, this is the set of releases in the return block of
  /// the callee associated with this parameter if it is @owned. If it
  /// is empty then we could not find any such releases.
  TinyPtrVector<SILInstruction *> CalleeRelease;

  /// The same as CalleeRelease, but the releases are post-dominated
  /// by the throw block, if it is a function which has a throw block.
  TinyPtrVector<SILInstruction *> CalleeReleaseInThrowBlock;

  /// The projection tree of this arguments.
  ProjectionTree ProjTree;

  ArgumentDescriptor() = delete;

  /// Initialize this argument descriptor with all information from A that we
  /// use in our optimization.
  ///
  /// *NOTE* We cache a lot of data from the argument and maintain a reference
  /// to the original argument. The reason why we do this is to make sure we
  /// have access to the original argument's state if we modify the argument
  /// when optimizing.
  ArgumentDescriptor(
      SILFunctionArgument *A,
      llvm::SpecificBumpPtrAllocator<ProjectionTreeNode> &Allocator)
      : Arg(A), PInfo(A->getKnownParameterInfo()), Index(A->getIndex()),
        Decl(A->getDecl()), IsEntirelyDead(false), WasErased(false),
        Explode(false), OwnedToGuaranteed(false),
        IsIndirectResult(A->isIndirectResult()), CalleeRelease(),
        CalleeReleaseInThrowBlock(),
        ProjTree(A->getModule(), A->getType(), Allocator) {
    if (!A->isIndirectResult()) {
      PInfo = Arg->getKnownParameterInfo();
    }
  }

  ArgumentDescriptor(const ArgumentDescriptor &) = delete;
  ArgumentDescriptor(ArgumentDescriptor &&) = default;
  ArgumentDescriptor &operator=(const ArgumentDescriptor &) = delete;
  ArgumentDescriptor &operator=(ArgumentDescriptor &&) = default;

  /// \returns true if this argument's convention is P.
  bool hasConvention(SILArgumentConvention P) const {
    return Arg->hasConvention(P);
  }

  /// Returns true if all function signature opt passes are able to process
  /// this.
  bool canOptimizeLiveArg() const {
    if (Arg->getType().isObject()) {
      return true;
    }

    // @in arguments of generic types can be processed.
    if (Arg->getType().hasArchetype() &&
        Arg->getType().isAddress() &&
        (Arg->hasConvention(SILArgumentConvention::Indirect_In) ||
         Arg->hasConvention(SILArgumentConvention::Indirect_In_Guaranteed)))
      return true;
    return false;
  }

  llvm::Optional<ValueOwnershipKind>
  getTransformedOwnershipKind(SILType SubTy) {
    if (IsEntirelyDead)
      return None;
    if (SubTy.isTrivial(*Arg->getFunction()))
      return Optional<ValueOwnershipKind>(ValueOwnershipKind::Any);
    if (OwnedToGuaranteed)
      return Optional<ValueOwnershipKind>(ValueOwnershipKind::Guaranteed);
    return Arg->getOwnershipKind();
  }
};

/// A structure that maintains all of the information about a specific
/// direct result that we are tracking.
struct ResultDescriptor {
  /// The original parameter info of this argument.
  SILResultInfo ResultInfo;
{'fraction_non_alphanumeric': 0.1261413913207192, 'fraction_numerical': 0.0018827073331450625, 'mean_word_length': 3.532423208191126, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 49, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5712459', 'n_tokens_mistral': 3129, 'n_tokens_neox': 3025, 'n_words': 897}