<commit_before>//===---- LoadStoreOpts.cpp - SIL Load/Store Optimizations Forwarding -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates redundent loads, dead stores, and performs load
// forwarding.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "load-store-opts"
#include "swift/SILPasses/Passes.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SILAnalysis/AliasAnalysis.h"
#include "swift/SILAnalysis/PostOrderAnalysis.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SILAnalysis/ValueTracking.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SILPasses/Utils/CFG.h"
#include "swift/SILPasses/Transforms.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"

using namespace swift;

STATISTIC(NumDeadStores,     "Number of dead stores removed");
STATISTIC(NumDupLoads,       "Number of dup loads removed");
STATISTIC(NumForwardedLoads, "Number of loads forwarded");

//===----------------------------------------------------------------------===//
//                             Utility Functions
//===----------------------------------------------------------------------===//

/// Returns true if this is an instruction that may have side effects in a
/// general sense but are inert from a load store perspective.
static bool isLSForwardingInertInstruction(SILInstruction *Inst) {
  switch (Inst->getKind()) {
  case ValueKind::StrongRetainInst:
  case ValueKind::RetainValueInst:
  case ValueKind::DeallocStackInst:
  case ValueKind::CondFailInst:
    return true;
  default:
    return false;
  }
}

static SILValue getForwardingValueForLS(const SILInstruction *I) {
  if (auto *SI = dyn_cast<StoreInst>(I))
    return SI->getSrc();
  return cast<LoadInst>(I);
}

static SILValue getAddressForLS(const SILInstruction *I) {
  if (auto *SI = dyn_cast<StoreInst>(I))
    return SI->getDest();
  return cast<LoadInst>(I)->getOperand();
}

static SILType getForwardingTypeForLS(const SILInstruction *I) {
  return getForwardingValueForLS(I).getType();
}

//===----------------------------------------------------------------------===//
//                      Forwarding Feasability Analysis
//===----------------------------------------------------------------------===//

namespace {

enum class ForwardingAnalysisResult {
  Failure,
  Normal,
  UncheckedAddress,
};

/// This is a move-only structure. Thus it has a private default constructor and
/// a deleted copy constructor.
class ForwardingAnalysis final {
  ForwardingAnalysisResult Result = ForwardingAnalysisResult::Failure;
  UncheckedAddrCastInst *UADCI = nullptr;
  Optional<ProjectionPath> Path;

public:
  ForwardingAnalysis(SILValue Address, LoadInst *LI,
                     UncheckedAddrCastInst *UADCI);
  ForwardingAnalysis(SILValue Address, LoadInst *LI);

  ForwardingAnalysis(const ForwardingAnalysis &) = delete;
  ForwardingAnalysis(ForwardingAnalysis &&FFA) = default;

  SILValue forward(SILValue Addr, SILValue StoredValue, LoadInst *LI);

  /// Returns true if this analysis is able to forward the analyzed load.
  bool canForward() const {
    switch (Result) {
    case ForwardingAnalysisResult::Failure:
      return false;
    case ForwardingAnalysisResult::Normal:
    case ForwardingAnalysisResult::UncheckedAddress:
      return true;
    }
  }

private:
  SILValue forwardAddrToLdWithExtractPath(SILValue Address,
                                          SILValue StoredValue,
                                          SILInstruction *Inst,
                                          SILValue InstOp);

  SILValue forwardAddrToUncheckedCastToLd(SILValue Address,
                                          SILValue StoredValue,
                                          LoadInst *LI);

  bool initializeWithUncheckedAddrCast(SILValue Address, LoadInst *LI,
                                       UncheckedAddrCastInst *InputUADCI);
};

} // end anonymous namespace

bool
ForwardingAnalysis::
initializeWithUncheckedAddrCast(SILValue Address, LoadInst *LI,
                                UncheckedAddrCastInst *InputUADCI) {
  assert(LI->getOperand().stripAddressProjections() == InputUADCI &&
         "We assume that the UADCI is the load's address stripped of "
         "address projections.");

  // First grab the address operand of our UADCI.
  SILValue UADCIOp = InputUADCI->getOperand();

  // Make sure that this is equal to our address. If not, bail.
  if (UADCIOp != Address)
    return false;

  // Construct the relevant bitcast.
  SILModule &Mod = InputUADCI->getModule();
  SILType InputTy = InputUADCI->getOperand().getType();
  SILType OutputTy = InputUADCI->getType();

  bool InputIsTrivial = InputTy.isTrivial(Mod);
  bool OutputIsTrivial = OutputTy.isTrivial(Mod);

  // If either are generic, bail.
  if (InputTy.hasArchetype() || OutputTy.hasArchetype())
    return false;

  // If we have a trivial input and a non-trivial output bail.
  if (InputIsTrivial && !OutputIsTrivial)
    return false;

  // The structs could have different size. We have code in the stdlib that
  // casts pointers to differently sized integer types. This code prevents
  // that we bitcast the values.
  if (OutputTy.getStructOrBoundGenericStruct() &&
      InputTy.getStructOrBoundGenericStruct()) {
    Result = ForwardingAnalysisResult::Failure;
    return false;
  }

  SILValue LdAddr = LI->getOperand();
  Path = std::move(ProjectionPath::getAddrProjectionPath(InputUADCI, LdAddr));
  if (!Path)
    return false;

  Result = ForwardingAnalysisResult::UncheckedAddress;
  UADCI = InputUADCI;
  return true;
}

/// Given an unchecked_addr_cast with various address projections using it,
/// check if we can forward the stored value.
ForwardingAnalysis::
ForwardingAnalysis(SILValue Address, LoadInst *LI,
                   UncheckedAddrCastInst *InputUADCI) {
  initializeWithUncheckedAddrCast(Address, LI, InputUADCI);
}

ForwardingAnalysis::ForwardingAnalysis(SILValue Address, LoadInst *LI) {
  // First if we have a store + unchecked_addr_cast + load, try to forward the
  // value the store using a bitcast.
  SILValue LIOpWithoutProjs = LI->getOperand().stripAddressProjections();
  if (auto *InputUADCI = dyn_cast<UncheckedAddrCastInst>(LIOpWithoutProjs))
    if (initializeWithUncheckedAddrCast(Address, LI, InputUADCI))
      return;<commit_msg>Remove line that I committed by mistake.<commit_after>//===---- LoadStoreOpts.cpp - SIL Load/Store Optimizations Forwarding -----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This pass eliminates redundent loads, dead stores, and performs load
// forwarding.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "load-store-opts"
#include "swift/SILPasses/Passes.h"
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SILAnalysis/AliasAnalysis.h"
#include "swift/SILAnalysis/PostOrderAnalysis.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SILAnalysis/ValueTracking.h"
#include "swift/SILPasses/Utils/Local.h"
#include "swift/SILPasses/Utils/CFG.h"
#include "swift/SILPasses/Transforms.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"

using namespace swift;

STATISTIC(NumDeadStores,     "Number of dead stores removed");
STATISTIC(NumDupLoads,       "Number of dup loads removed");
STATISTIC(NumForwardedLoads, "Number of loads forwarded");

//===----------------------------------------------------------------------===//
//                             Utility Functions
//===----------------------------------------------------------------------===//

/// Returns true if this is an instruction that may have side effects in a
/// general sense but are inert from a load store perspective.
static bool isLSForwardingInertInstruction(SILInstruction *Inst) {
  switch (Inst->getKind()) {
  case ValueKind::StrongRetainInst:
  case ValueKind::RetainValueInst:
  case ValueKind::DeallocStackInst:
  case ValueKind::CondFailInst:
    return true;
  default:
    return false;
  }
}

static SILValue getForwardingValueForLS(const SILInstruction *I) {
  if (auto *SI = dyn_cast<StoreInst>(I))
    return SI->getSrc();
  return cast<LoadInst>(I);
}

static SILValue getAddressForLS(const SILInstruction *I) {
  if (auto *SI = dyn_cast<StoreInst>(I))
    return SI->getDest();
  return cast<LoadInst>(I)->getOperand();
}

static SILType getForwardingTypeForLS(const SILInstruction *I) {
  return getForwardingValueForLS(I).getType();
}

//===----------------------------------------------------------------------===//
//                      Forwarding Feasability Analysis
//===----------------------------------------------------------------------===//

namespace {

enum class ForwardingAnalysisResult {
  Failure,
  Normal,
  UncheckedAddress,
};

/// This is a move-only structure. Thus it has a private default constructor and
/// a deleted copy constructor.
class ForwardingAnalysis final {
  ForwardingAnalysisResult Result = ForwardingAnalysisResult::Failure;
  UncheckedAddrCastInst *UADCI = nullptr;
  Optional<ProjectionPath> Path;

public:
  ForwardingAnalysis(SILValue Address, LoadInst *LI,
                     UncheckedAddrCastInst *UADCI);
  ForwardingAnalysis(SILValue Address, LoadInst *LI);

  ForwardingAnalysis(const ForwardingAnalysis &) = delete;
  ForwardingAnalysis(ForwardingAnalysis &&FFA) = default;

  SILValue forward(SILValue Addr, SILValue StoredValue, LoadInst *LI);

  /// Returns true if this analysis is able to forward the analyzed load.
  bool canForward() const {
    switch (Result) {
    case ForwardingAnalysisResult::Failure:
      return false;
    case ForwardingAnalysisResult::Normal:
    case ForwardingAnalysisResult::UncheckedAddress:
      return true;
    }
  }

private:
  SILValue forwardAddrToLdWithExtractPath(SILValue Address,
                                          SILValue StoredValue,
                                          SILInstruction *Inst,
                                          SILValue InstOp);

  SILValue forwardAddrToUncheckedCastToLd(SILValue Address,
                                          SILValue StoredValue,
                                          LoadInst *LI);

  bool initializeWithUncheckedAddrCast(SILValue Address, LoadInst *LI,
                                       UncheckedAddrCastInst *InputUADCI);
};

} // end anonymous namespace

bool
ForwardingAnalysis::
initializeWithUncheckedAddrCast(SILValue Address, LoadInst *LI,
                                UncheckedAddrCastInst *InputUADCI) {
  assert(LI->getOperand().stripAddressProjections() == InputUADCI &&
         "We assume that the UADCI is the load's address stripped of "
         "address projections.");

  // First grab the address operand of our UADCI.
  SILValue UADCIOp = InputUADCI->getOperand();

  // Make sure that this is equal to our address. If not, bail.
  if (UADCIOp != Address)
    return false;

  // Construct the relevant bitcast.
  SILModule &Mod = InputUADCI->getModule();
  SILType InputTy = InputUADCI->getOperand().getType();
  SILType OutputTy = InputUADCI->getType();

  bool InputIsTrivial = InputTy.isTrivial(Mod);
  bool OutputIsTrivial = OutputTy.isTrivial(Mod);

  // If either are generic, bail.
  if (InputTy.hasArchetype() || OutputTy.hasArchetype())
    return false;

  // If we have a trivial input and a non-trivial output bail.
  if (InputIsTrivial && !OutputIsTrivial)
    return false;

  // The structs could have different size. We have code in the stdlib that
  // casts pointers to differently sized integer types. This code prevents
  // that we bitcast the values.
  if (OutputTy.getStructOrBoundGenericStruct() &&
      InputTy.getStructOrBoundGenericStruct())
    return false;

  SILValue LdAddr = LI->getOperand();
  Path = std::move(ProjectionPath::getAddrProjectionPath(InputUADCI, LdAddr));
  if (!Path)
    return false;

  Result = ForwardingAnalysisResult::UncheckedAddress;
  UADCI = InputUADCI;
  return true;
}

/// Given an unchecked_addr_cast with various address projections using it,
/// check if we can forward the stored value.
ForwardingAnalysis::
ForwardingAnalysis(SILValue Address, LoadInst *LI,
                   UncheckedAddrCastInst *InputUADCI) {
  initializeWithUncheckedAddrCast(Address, LI, InputUADCI);
}

ForwardingAnalysis::ForwardingAnalysis(SILValue Address, LoadInst *LI) {
  // First if we have a store + unchecked_addr_cast + load, try to forward the
  // value the store using a bitcast.
  SILValue LIOpWithoutProjs = LI->getOperand().stripAddressProjections();
  if (auto *InputUADCI = dyn_cast<UncheckedAddrCastInst>(LIOpWithoutProjs))
    if (initializeWithUncheckedAddrCast(Address, LI, InputUADCI))
      return;
{'fraction_non_alphanumeric': 0.15906658103189894, 'fraction_numerical': 0.0014272461285948761, 'mean_word_length': 2.6849855377333682, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3722088', 'n_tokens_mistral': 3975, 'n_tokens_neox': 3870, 'n_words': 1049}