//===------ Simplify.cpp ----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Simplify a SCoP by removing unnecessary statements and accesses.
//
//===----------------------------------------------------------------------===//

#include "polly/Simplify.h"
#include "polly/ScopInfo.h"
#include "polly/ScopPass.h"
#include "polly/Support/GICHelper.h"
#include "polly/Support/ISLOStream.h"
#include "polly/Support/ISLTools.h"
#include "polly/Support/VirtualInstruction.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "polly-simplify"

using namespace llvm;
using namespace polly;

namespace {

#define TWO_STATISTICS(VARNAME, DESC)                                          \
  static llvm::Statistic VARNAME[2] = {                                        \
      {DEBUG_TYPE, #VARNAME "0", DESC " (first)"},                             \
      {DEBUG_TYPE, #VARNAME "1", DESC " (second)"}}

/// Number of max disjuncts we allow in removeOverwrites(). This is to avoid
/// that the analysis of accesses in a statement is becoming too complex. Chosen
/// to be relatively small because all the common cases should access only few
/// array elements per statement.
static int const SimplifyMaxDisjuncts = 4;

TWO_STATISTICS(ScopsProcessed, "Number of SCoPs processed");
TWO_STATISTICS(ScopsModified, "Number of SCoPs simplified");

TWO_STATISTICS(TotalOverwritesRemoved, "Number of removed overwritten writes");
TWO_STATISTICS(TotalWritesCoalesced, "Number of writes coalesced with another");
TWO_STATISTICS(TotalRedundantWritesRemoved,
               "Number of writes of same value removed in any SCoP");
TWO_STATISTICS(TotalEmptyPartialAccessesRemoved,
               "Number of empty partial accesses removed");
TWO_STATISTICS(TotalDeadAccessesRemoved, "Number of dead accesses removed");
TWO_STATISTICS(TotalDeadInstructionsRemoved,
               "Number of unused instructions removed");
TWO_STATISTICS(TotalStmtsRemoved, "Number of statements removed in any SCoP");

TWO_STATISTICS(NumValueWrites, "Number of scalar value writes after Simplify");
TWO_STATISTICS(
    NumValueWritesInLoops,
    "Number of scalar value writes nested in affine loops after Simplify");
TWO_STATISTICS(NumPHIWrites,
               "Number of scalar phi writes after the first simplification");
TWO_STATISTICS(
    NumPHIWritesInLoops,
    "Number of scalar phi writes nested in affine loops after Simplify");
TWO_STATISTICS(NumSingletonWrites, "Number of singleton writes after Simplify");
TWO_STATISTICS(
    NumSingletonWritesInLoops,
    "Number of singleton writes nested in affine loops after Simplify");

static bool isImplicitRead(MemoryAccess *MA) {
  return MA->isRead() && MA->isOriginalScalarKind();
}

static bool isExplicitAccess(MemoryAccess *MA) {
  return MA->isOriginalArrayKind();
}

static bool isImplicitWrite(MemoryAccess *MA) {
  return MA->isWrite() && MA->isOriginalScalarKind();
}

/// Like isl::union_map::add_map, but may also return an underapproximated
/// result if getting too complex.
///
/// This is implemented by adding disjuncts to the results until the limit is
/// reached.
static isl::union_map underapproximatedAddMap(isl::union_map UMap,
                                              isl::map Map) {
  if (UMap.is_null() || Map.is_null())
    return {};

  isl::map PrevMap = UMap.extract_map(Map.get_space());

  // Fast path: If known that we cannot exceed the disjunct limit, just add
  // them.
  if (isl_map_n_basic_map(PrevMap.get()) + isl_map_n_basic_map(Map.get()) <=
      SimplifyMaxDisjuncts)
    return UMap.add_map(Map);

  isl::map Result = isl::map::empty(PrevMap.get_space());
  for (isl::basic_map BMap : PrevMap.get_basic_map_list()) {
    if (Result.n_basic_map() > SimplifyMaxDisjuncts)
      break;
    Result = Result.unite(BMap);
  }
  for (isl::basic_map BMap : Map.get_basic_map_list()) {
    if (isl_map_n_basic_map(Result.get()) > SimplifyMaxDisjuncts)
      break;
    Result = Result.unite(BMap);
  }

  isl::union_map UResult =
      UMap.subtract(isl::map::universe(PrevMap.get_space()));
  UResult.add_map(Result);

  return UResult;
}

class Simplify : public ScopPass {
private:
  /// The invocation id (if there are multiple instances in the pass manager's
  /// pipeline) to determine which statistics to update.
  int CallNo;

  /// The last/current SCoP that is/has been processed.
  Scop *S;

  /// Number of writes that are overwritten anyway.
  int OverwritesRemoved = 0;

  /// Number of combined writes.
  int WritesCoalesced = 0;

  /// Number of redundant writes removed from this SCoP.
  int RedundantWritesRemoved = 0;

  /// Number of writes with empty access domain removed.
  int EmptyPartialAccessesRemoved = 0;

  /// Number of unused accesses removed from this SCoP.
  int DeadAccessesRemoved = 0;

  /// Number of unused instructions removed from this SCoP.
  int DeadInstructionsRemoved = 0;

  /// Number of unnecessary statements removed from the SCoP.
  int StmtsRemoved = 0;

  /// Return whether at least one simplification has been applied.
  bool isModified() const {
    return OverwritesRemoved > 0 || WritesCoalesced > 0 ||
           RedundantWritesRemoved > 0 || EmptyPartialAccessesRemoved > 0 ||
           DeadAccessesRemoved > 0 || DeadInstructionsRemoved > 0 ||
           StmtsRemoved > 0;
  }

  /// Remove writes that are overwritten unconditionally later in the same
  /// statement.
  ///
  /// There must be no read of the same value between the write (that is to be
  /// removed) and the overwrite.
  void removeOverwrites() {
    for (auto &Stmt : *S) {
      isl::set Domain = Stmt.getDomain();
      isl::union_map WillBeOverwritten =
          isl::union_map::empty(S->getParamSpace());

      SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));

      // Iterate in reverse order, so the overwrite comes before the write that
      // is to be removed.
      for (auto *MA : reverse(Accesses)) {

        // In region statements, the explicit accesses can be in blocks that are
        // can be executed in any order. We therefore process only the implicit
        // writes and stop after that.
        if (Stmt.isRegionStmt() && isExplicitAccess(MA))
          break;

        auto AccRel = MA->getAccessRelation();
        AccRel = AccRel.intersect_domain(Domain);
        AccRel = AccRel.intersect_params(S->getContext());

        // If a value is read in-between, do not consider it as overwritten.
        if (MA->isRead()) {
          // Invalidate all overwrites for the array it accesses to avoid too
          // complex isl sets.
          isl::map AccRelUniv = isl::map::universe(AccRel.get_space());
          WillBeOverwritten = WillBeOverwritten.subtract(AccRelUniv);
          continue;
        }

        // If all of a write's elements are overwritten, remove it.
        isl::union_map AccRelUnion = AccRel;
        if (AccRelUnion.is_subset(WillBeOverwritten)) {
          LLVM_DEBUG(dbgs() << "Removing " << MA
                            << " which will be overwritten anyway\n");

          Stmt.removeSingleMemoryAccess(MA);
          OverwritesRemoved++;
          TotalOverwritesRemoved[CallNo]++;
        }

        // Unconditional writes overwrite other values.
        if (MA->isMustWrite()) {
          // Avoid too complex isl sets. If necessary, throw away some of the
          // knowledge.
          WillBeOverwritten =
              underapproximatedAddMap(WillBeOverwritten, AccRel);
        }
      }
    }
  }

  /// Combine writes that write the same value if possible.
  ///
  /// This function is able to combine:
  /// - Partial writes with disjoint domain.
  /// - Writes that write to the same array element.
  ///
  /// In all cases, both writes must write the same values.
  void coalesceWrites() {
    for (auto &Stmt : *S) {
      isl::set Domain = Stmt.getDomain().intersect_params(S->getContext());

      // We let isl do the lookup for the same-value condition. For this, we
      // wrap llvm::Value into an isl::set such that isl can do the lookup in
      // its hashtable implementation. llvm::Values are only compared within a
      // ScopStmt, so the map can be local to this scope. TODO: Refactor with
      // ZoneAlgorithm::makeValueSet()
      SmallDenseMap<Value *, isl::set> ValueSets;
      auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
        assert(V);
        isl::set &Result = ValueSets[V];
        if (Result.is_null()) {
          isl::ctx Ctx = S->getIslCtx();
          std::string Name =
              getIslCompatibleName("Val", V, ValueSets.size() - 1,
                                   std::string(), UseInstructionNames);
          isl::id Id = isl::id::alloc(Ctx, Name, V);
          Result = isl::set::universe(
              isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
        }
        return Result;
      };

      // List of all eligible (for coalescing) writes of the future.
      // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
      isl::union_map FutureWrites = isl::union_map::empty(S->getParamSpace());

      // Iterate over accesses from the last to the first.
      SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
      for (MemoryAccess *MA : reverse(Accesses)) {
        // In region statements, the explicit accesses can be in blocks that can
        // be executed in any order. We therefore process only the implicit
        // writes and stop after that.
        if (Stmt.isRegionStmt() && isExplicitAccess(MA))
          break;

        // { Domain[] -> Element[] }
        isl::map AccRel =
            MA->getLatestAccessRelation().intersect_domain(Domain);

        // { [Domain[] -> Element[]] }
        isl::set AccRelWrapped = AccRel.wrap();

        // { Value[] }
        isl::set ValSet;

        if (MA->isMustWrite() && (MA->isOriginalScalarKind() ||
                                  isa<StoreInst>(MA->getAccessInstruction()))) {
          // Normally, tryGetValueStored() should be used to determine which
          // element is written, but it can return nullptr; For PHI accesses,
          // getAccessValue() returns the PHI instead of the PHI's incoming
          // value. In this case, where we only compare values of a single
          // statement, this is fine, because within a statement, a PHI in a
          // successor block has always the same value as the incoming write. We
          // still preferably use the incoming value directly so we also catch
          // direct uses of that.
          Value *StoredVal = MA->tryGetValueStored();
          if (!StoredVal)
            StoredVal = MA->getAccessValue();
          ValSet = makeValueSet(StoredVal);

          // { Domain[] }
          isl::set AccDomain = AccRel.domain();

          // Parts of the statement's domain that is not written by this access.
          isl::set UndefDomain = Domain.subtract(AccDomain);

          // { Element[] }
          isl::set ElementUniverse =
              isl::set::universe(AccRel.get_space().range());

          // { Domain[] -> Element[] }
          isl::map UndefAnything =
              isl::map::from_domain_and_range(UndefDomain, ElementUniverse);

          // We are looking a compatible write access. The other write can
          // access these elements...
          isl::map AllowedAccesses = AccRel.unite(UndefAnything);

          // ... and must write the same value.
          // { [Domain[] -> Element[]] -> Value[] }
          isl::map Filter =
              isl::map::from_domain_and_range(AllowedAccesses.wrap(), ValSet);

          // Lookup future write that fulfills these conditions.
          // { [[Domain[] -> Element[]] -> Value[]] -> MemoryAccess[] }
          isl::union_map Filtered =
              FutureWrites.uncurry().intersect_domain(Filter.wrap());

          // Iterate through the candidates.
          for (isl::map Map : Filtered.get_map_list()) {
            MemoryAccess *OtherMA = (MemoryAccess *)Map.get_space()
                                        .get_tuple_id(isl::dim::out)
                                        .get_user();

            isl::map OtherAccRel =
                OtherMA->getLatestAccessRelation().intersect_domain(Domain);

            // The filter only guaranteed that some of OtherMA's accessed
            // elements are allowed. Verify that it only accesses allowed
            // elements. Otherwise, continue with the next candidate.
            if (!OtherAccRel.is_subset(AllowedAccesses).is_true())
              continue;

            // The combined access relation.
            // { Domain[] -> Element[] }
            isl::map NewAccRel = AccRel.unite(OtherAccRel);
            simplify(NewAccRel);

            // Carry out the coalescing.
            Stmt.removeSingleMemoryAccess(MA);
            OtherMA->setNewAccessRelation(NewAccRel);

            // We removed MA, OtherMA takes its role.
            MA = OtherMA;

            TotalWritesCoalesced[CallNo]++;
            WritesCoalesced++;

            // Don't look for more candidates.
            break;
          }
        }

        // Two writes cannot be coalesced if there is another access (to some of
        // the written elements) between them. Remove all visited write accesses
        // from the list of eligible writes. Don't just remove the accessed
        // elements, but any MemoryAccess that touches any of the invalidated
        // elements.
        SmallPtrSet<MemoryAccess *, 2> TouchedAccesses;
        for (isl::map Map :
             FutureWrites.intersect_domain(AccRelWrapped).get_map_list()) {
          MemoryAccess *MA = (MemoryAccess *)Map.get_space()
                                 .range()
                                 .unwrap()
                                 .get_tuple_id(isl::dim::out)
                                 .get_user();
          TouchedAccesses.insert(MA);
        }
        isl::union_map NewFutureWrites =
            isl::union_map::empty(FutureWrites.get_space());
        for (isl::map FutureWrite : FutureWrites.get_map_list()) {
          MemoryAccess *MA = (MemoryAccess *)FutureWrite.get_space()
                                 .range()
                                 .unwrap()
                                 .get_tuple_id(isl::dim::out)
                                 .get_user();
          if (!TouchedAccesses.count(MA))
            NewFutureWrites = NewFutureWrites.add_map(FutureWrite);
        }
        FutureWrites = NewFutureWrites;

        if (MA->isMustWrite() && !ValSet.is_null()) {
          // { MemoryAccess[] }
          auto AccSet =
              isl::set::universe(isl::space(S->getIslCtx(), 0, 0)
                                     .set_tuple_id(isl::dim::set, MA->getId()));

          // { Val[] -> MemoryAccess[] }
          isl::map ValAccSet = isl::map::from_domain_and_range(ValSet, AccSet);

          // { [Domain[] -> Element[]] -> [Value[] -> MemoryAccess[]] }
          isl::map AccRelValAcc =
              isl::map::from_domain_and_range(AccRelWrapped, ValAccSet.wrap());
          FutureWrites = FutureWrites.add_map(AccRelValAcc);
        }
      }
    }
  }

  /// Remove writes that just write the same value already stored in the
  /// element.
  void removeRedundantWrites() {
    for (auto &Stmt : *S) {
      SmallDenseMap<Value *, isl::set> ValueSets;
      auto makeValueSet = [&ValueSets, this](Value *V) -> isl::set {
        assert(V);
        isl::set &Result = ValueSets[V];
        if (Result.is_null()) {
          isl_ctx *Ctx = S->getIslCtx().get();
          std::string Name =
              getIslCompatibleName("Val", V, ValueSets.size() - 1,
                                   std::string(), UseInstructionNames);
          isl::id Id = isl::manage(isl_id_alloc(Ctx, Name.c_str(), V));
          Result = isl::set::universe(
              isl::space(Ctx, 0, 0).set_tuple_id(isl::dim::set, Id));
        }
        return Result;
      };

      isl::set Domain = Stmt.getDomain();
      Domain = Domain.intersect_params(S->getContext());

      // List of element reads that still have the same value while iterating
      // through the MemoryAccesses.
      // { [Domain[] -> Element[]] -> Val[] }
      isl::union_map Known = isl::union_map::empty(S->getParamSpace());

      SmallVector<MemoryAccess *, 32> Accesses(getAccessesInOrder(Stmt));
      for (MemoryAccess *MA : Accesses) {
        // Is the memory access in a defined order relative to the other
        // accesses? In region statements, only the first and the last accesses
        // have defined order. Execution of those in the middle may depend on
        // runtime conditions an therefore cannot be modified.
        bool IsOrdered =
            Stmt.isBlockStmt() || MA->isOriginalScalarKind() ||
            (!S->getBoxedLoops().size() && MA->getAccessInstruction() &&
             Stmt.getEntryBlock() == MA->getAccessInstruction()->getParent());

        isl::map AccRel = MA->getAccessRelation();
        AccRel = AccRel.intersect_domain(Domain);
        isl::set AccRelWrapped = AccRel.wrap();

        // Determine whether a write is redundant (stores only values that are
        // already present in the written array elements) and remove it if this
        // is the case.
        if (IsOrdered && MA->isMustWrite() &&
            (isa<StoreInst>(MA->getAccessInstruction()) ||
             MA->isOriginalScalarKind())) {
          Value *StoredVal = MA->tryGetValueStored();
          if (!StoredVal)
            StoredVal = MA->getAccessValue();

          if (StoredVal) {
            // Lookup in the set of known values.
            isl::map AccRelStoredVal = isl::map::from_domain_and_range(
                AccRelWrapped, makeValueSet(StoredVal));
            if (isl::union_map(AccRelStoredVal).is_subset(Known)) {
              LLVM_DEBUG(dbgs() << "Cleanup of " << MA << ":\n");
              LLVM_DEBUG(dbgs() << "      Scalar: " << *StoredVal << "\n");
              LLVM_DEBUG(dbgs() << "      AccRel: " << AccRel << "\n");

              Stmt.removeSingleMemoryAccess(MA);

              RedundantWritesRemoved++;
              TotalRedundantWritesRemoved[CallNo]++;
            }
          }
        }

        // Update the know values set.
        if (MA->isRead()) {
          // Loaded values are the currently known values of the array element
          // it was loaded from.
          Value *LoadedVal = MA->getAccessValue();
          if (LoadedVal && IsOrdered) {
            isl::map AccRelVal = isl::map::from_domain_and_range(
                AccRelWrapped, makeValueSet(LoadedVal));

            Known = Known.add_map(AccRelVal);
          }
        } else if (MA->isWrite()) {
          // Remove (possibly) overwritten values from the known elements set.
          // We remove all elements of the accessed array to avoid too complex
          // isl sets.
          isl::set AccRelUniv = isl::set::universe(AccRelWrapped.get_space());
          Known = Known.subtract_domain(AccRelUniv);

          // At this point, we could add the written value of must-writes.
          // However, writing same values is already handled by
          // coalesceWrites().
        }
      }
    }
  }

  /// Remove statements without side effects.
  void removeUnnecessaryStmts() {
    auto NumStmtsBefore = S->getSize();
    S->simplifySCoP(true);
    assert(NumStmtsBefore >= S->getSize());
    StmtsRemoved = NumStmtsBefore - S->getSize();
    LLVM_DEBUG(dbgs() << "Removed " << StmtsRemoved << " (of " << NumStmtsBefore
                      << ") statements\n");
    TotalStmtsRemoved[CallNo] += StmtsRemoved;
  }

  /// Remove accesses that have an empty domain.
  void removeEmptyPartialAccesses() {
    for (ScopStmt &Stmt : *S) {
      // Defer the actual removal to not invalidate iterators.
      SmallVector<MemoryAccess *, 8> DeferredRemove;

      for (MemoryAccess *MA : Stmt) {
        if (!MA->isWrite())
          continue;

        isl::map AccRel = MA->getAccessRelation();
        if (!AccRel.is_empty().is_true())
          continue;

        LLVM_DEBUG(
            dbgs() << "Removing " << MA
                   << " because it's a partial access that never occurs\n");
        DeferredRemove.push_back(MA);
      }

      for (MemoryAccess *MA : DeferredRemove) {
        Stmt.removeSingleMemoryAccess(MA);
        EmptyPartialAccessesRemoved++;
        TotalEmptyPartialAccessesRemoved[CallNo]++;
      }
    }
  }

  /// Mark all reachable instructions and access, and sweep those that are not
  /// reachable.
  void markAndSweep(LoopInfo *LI) {
    DenseSet<MemoryAccess *> UsedMA;
    DenseSet<VirtualInstruction> UsedInsts;

    // Get all reachable instructions and accesses.
    markReachable(S, LI, UsedInsts, UsedMA);

    // Remove all non-reachable accesses.
    // We need get all MemoryAccesses first, in order to not invalidate the
    // iterators when removing them.
    SmallVector<MemoryAccess *, 64> AllMAs;
    for (ScopStmt &Stmt : *S)
      AllMAs.append(Stmt.begin(), Stmt.end());

    for (MemoryAccess *MA : AllMAs) {
      if (UsedMA.count(MA))
        continue;
      LLVM_DEBUG(dbgs() << "Removing " << MA
                        << " because its value is not used\n");
      ScopStmt *Stmt = MA->getStatement();
      Stmt->removeSingleMemoryAccess(MA);

      DeadAccessesRemoved++;
      TotalDeadAccessesRemoved[CallNo]++;
    }

    // Remove all non-reachable instructions.
    for (ScopStmt &Stmt : *S) {
      // Note that for region statements, we can only remove the non-terminator
      // instructions of the entry block. All other instructions are not in the
      // instructions list, but implicitly always part of the statement.

      SmallVector<Instruction *, 32> AllInsts(Stmt.insts_begin(),
                                              Stmt.insts_end());
      SmallVector<Instruction *, 32> RemainInsts;

      for (Instruction *Inst : AllInsts) {
        auto It = UsedInsts.find({&Stmt, Inst});
        if (It == UsedInsts.end()) {
          LLVM_DEBUG(dbgs() << "Removing "; Inst->print(dbgs());
                     dbgs() << " because it is not used\n");
          DeadInstructionsRemoved++;
          TotalDeadInstructionsRemoved[CallNo]++;
          continue;
        }

        RemainInsts.push_back(Inst);

        // If instructions appear multiple times, keep only the first.
        UsedInsts.erase(It);
      }

      // Set the new instruction list to be only those we did not remove.
      Stmt.setInstructions(RemainInsts);
    }
  }

  /// Print simplification statistics to @p OS.
  void printStatistics(llvm::raw_ostream &OS, int Indent = 0) const {
    OS.indent(Indent) << "Statistics {\n";
    OS.indent(Indent + 4) << "Overwrites removed: " << OverwritesRemoved
                          << '\n';
    OS.indent(Indent + 4) << "Partial writes coalesced: " << WritesCoalesced
                          << "\n";
    OS.indent(Indent + 4) << "Redundant writes removed: "
                          << RedundantWritesRemoved << "\n";
    OS.indent(Indent + 4) << "Accesses with empty domains removed: "
                          << EmptyPartialAccessesRemoved << "\n";
    OS.indent(Indent + 4) << "Dead accesses removed: " << DeadAccessesRemoved
                          << '\n';
    OS.indent(Indent + 4) << "Dead instructions removed: "
                          << DeadInstructionsRemoved << '\n';
    OS.indent(Indent + 4) << "Stmts removed: " << StmtsRemoved << "\n";
    OS.indent(Indent) << "}\n";
  }

  /// Print the current state of all MemoryAccesses to @p OS.
  void printAccesses(llvm::raw_ostream &OS, int Indent = 0) const {
    OS.indent(Indent) << "After accesses {\n";
    for (auto &Stmt : *S) {
      OS.indent(Indent + 4) << Stmt.getBaseName() << "\n";
      for (auto *MA : Stmt)
        MA->print(OS);
    }
    OS.indent(Indent) << "}\n";
  }

public:
  static char ID;
  explicit Simplify(int CallNo = 0) : ScopPass(ID), CallNo(CallNo) {}

  virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequiredTransitive<ScopInfoRegionPass>();
    AU.addRequired<LoopInfoWrapperPass>();
    AU.setPreservesAll();
  }

  virtual bool runOnScop(Scop &S) override {
    // Reset statistics of last processed SCoP.
    releaseMemory();
    assert(!isModified());

    // Prepare processing of this SCoP.
    this->S = &S;
    ScopsProcessed[CallNo]++;

    LLVM_DEBUG(dbgs() << "Removing partial writes that never happen...\n");
    removeEmptyPartialAccesses();

    LLVM_DEBUG(dbgs() << "Removing overwrites...\n");
    removeOverwrites();

    LLVM_DEBUG(dbgs() << "Coalesce partial writes...\n");
    coalesceWrites();

    LLVM_DEBUG(dbgs() << "Removing redundant writes...\n");
    removeRedundantWrites();

    LLVM_DEBUG(dbgs() << "Cleanup unused accesses...\n");
    LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
    markAndSweep(LI);

    LLVM_DEBUG(dbgs() << "Removing statements without side effects...\n");
    removeUnnecessaryStmts();

    if (isModified())
      ScopsModified[CallNo]++;
    LLVM_DEBUG(dbgs() << "\nFinal Scop:\n");
    LLVM_DEBUG(dbgs() << S);

    auto ScopStats = S.getStatistics();
    NumValueWrites[CallNo] += ScopStats.NumValueWrites;
    NumValueWritesInLoops[CallNo] += ScopStats.NumValueWritesInLoops;
    NumPHIWrites[CallNo] += ScopStats.NumPHIWrites;
    NumPHIWritesInLoops[CallNo] += ScopStats.NumPHIWritesInLoops;
    NumSingletonWrites[CallNo] += ScopStats.NumSingletonWrites;
    NumSingletonWritesInLoops[CallNo] += ScopStats.NumSingletonWritesInLoops;

    return false;
  }

  virtual void printScop(raw_ostream &OS, Scop &S) const override {
    assert(&S == this->S &&
           "Can only print analysis for the last processed SCoP");
    printStatistics(OS);

    if (!isModified()) {
      OS << "SCoP could not be simplified\n";
      return;
    }
    printAccesses(OS);
  }

  virtual void releaseMemory() override {
    S = nullptr;

    OverwritesRemoved = 0;
    WritesCoalesced = 0;
    RedundantWritesRemoved = 0;
    EmptyPartialAccessesRemoved = 0;
    DeadAccessesRemoved = 0;
    DeadInstructionsRemoved = 0;
    StmtsRemoved = 0;
  }
};

char Simplify::ID;
} // anonymous namespace

namespace polly {
SmallVector<MemoryAccess *, 32> getAccessesInOrder(ScopStmt &Stmt) {

  SmallVector<MemoryAccess *, 32> Accesses;

  for (MemoryAccess *MemAcc : Stmt)
    if (isImplicitRead(MemAcc))
      Accesses.push_back(MemAcc);

  for (MemoryAccess *MemAcc : Stmt)
    if (isExplicitAccess(MemAcc))
      Accesses.push_back(MemAcc);

  for (MemoryAccess *MemAcc : Stmt)
    if (isImplicitWrite(MemAcc))
      Accesses.push_back(MemAcc);

  return Accesses;
}
} // namespace polly

Pass *polly::createSimplifyPass(int CallNo) { return new Simplify(CallNo); }

INITIALIZE_PASS_BEGIN(Simplify, "polly-simplify", "Polly - Simplify", false,
                      false)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(Simplify, "polly-simplify", "Polly - Simplify", false,
                    false)
