<commit_before>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <exception>
#include <vector>
#include <string>

#include "itkImage.h"
#include "itkImageFileWriter.h"

#include "antsImage.h"

namespace py = pybind11;

template<typename InImageType, typename OutImageType>
ANTsImage<OutImageType> antsImageClone( ANTsImage<InImageType> antsImage )
{
  typedef typename InImageType::Pointer InImagePointerType;
  InImagePointerType in_image = as< InImageType >( antsImage );

  typename OutImageType::Pointer out_image = OutImageType::New() ;
  out_image->SetRegions( in_image->GetLargestPossibleRegion() ) ;
  out_image->SetSpacing( in_image->GetSpacing() ) ;
  out_image->SetOrigin( in_image->GetOrigin() ) ;
  out_image->SetDirection( in_image->GetDirection() );
  //out_image->CopyInformation( in_image );
  out_image->Allocate() ;

  itk::ImageRegionConstIterator< InImageType > in_iterator( in_image , in_image->GetLargestPossibleRegion() ) ;
  itk::ImageRegionIterator< OutImageType > out_iterator( out_image , out_image->GetLargestPossibleRegion() ) ;
  for( in_iterator.GoToBegin() , out_iterator.GoToBegin() ; !in_iterator.IsAtEnd() ; ++in_iterator , ++out_iterator )
    {
    out_iterator.Set( static_cast< typename OutImageType::PixelType >( in_iterator.Get() ) ) ;
    }
  return wrap< OutImageType >( out_image );
}

template <typename InImageType, typename OutImageType>
void wrapantsImageClone(py::module & m, std::string const & suffix) {
  m.def(("antsImageClone"+suffix).c_str(), &antsImageClone<InImageType,OutImageType>);
}
//pixels: Image, VectorImage
//types: unsigned char, unsigned int, float, double
//dims: 2, 3, 4
PYBIND11_MODULE(antsImageClone, m)
{
  // dim = 2
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<unsigned char,2>>(m, "UC2UC2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<unsigned int,2>>(m, "UC2UI2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<float,2>>(m, "UC2F2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<double,2>>(m, "UC2D2");

  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<unsigned char,2>>(m, "UI2UC2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<unsigned int,2>>(m, "UI2UI2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<float,2>>(m, "UI2F2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<double,2>>(m, "UI2D2");

  wrapantsImageClone<itk::Image<float,2>,itk::Image<unsigned char,2>>(m, "F2UC2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<unsigned int,2>>(m, "F2UI2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<float,2>>(m, "F2F2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<double,2>>(m, "F2D2");

  wrapantsImageClone<itk::Image<double,2>,itk::Image<unsigned char,2>>(m, "D2UC2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<unsigned int,2>>(m, "D2UI2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<float,2>>(m, "D2F2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<double,2>>(m, "D2D2");

  // dim = 3
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<unsigned char,3>>(m, "UC3UC2");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<unsigned int,3>>(m, "UC3UI3");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<float,3>>(m, "UC3F3");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<double,3>>(m, "UC3D3");

  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<unsigned char,3>>(m, "UI3UC3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<unsigned int,3>>(m, "UI3UI3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<float,3>>(m, "UI3F3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<double,3>>(m, "UI3D3");

  wrapantsImageClone<itk::Image<float,3>,itk::Image<unsigned char,3>>(m, "F3UC3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<unsigned int,3>>(m, "F3UI3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<float,3>>(m, "F3F3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<double,3>>(m, "F3D3");

  wrapantsImageClone<itk::Image<double,3>,itk::Image<unsigned char,3>>(m, "D3UC3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<unsigned int,3>>(m, "D3UI3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<float,3>>(m, "D3F3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<double,3>>(m, "D3D3");

  // dim = 4
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<unsigned char,4>>(m, "UC4UC4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<unsigned int,4>>(m, "UC4UI4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<float,4>>(m, "UC4F4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<double,4>>(m, "UC4D4");

  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<unsigned char,4>>(m, "UI4UC4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<unsigned int,4>>(m, "UI4UI4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<float,4>>(m, "UI4F4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<double,4>>(m, "UI4D4");

  wrapantsImageClone<itk::Image<float,4>,itk::Image<unsigned char,4>>(m, "F4UC4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<unsigned int,4>>(m, "F4UI4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<float,4>>(m, "F4F4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<double,4>>(m, "F4D4");

  wrapantsImageClone<itk::Image<double,4>,itk::Image<unsigned char,4>>(m, "D4UC4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<unsigned int,4>>(m, "D4UI4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<float,4>>(m, "D4F4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<double,4>>(m, "D4D4");

}

<commit_msg>imageClone<commit_after>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <exception>
#include <vector>
#include <string>

#include "itkImage.h"
#include "itkImageFileWriter.h"

#include "antsImage.h"

namespace py = pybind11;

template<typename InImageType, typename OutImageType>
ANTsImage<OutImageType> antsImageClone( ANTsImage<InImageType> antsImage )
{
  typedef typename InImageType::Pointer InImagePointerType;
  InImagePointerType in_image = as< InImageType >( antsImage );

  typename OutImageType::Pointer out_image = OutImageType::New() ;
  out_image->SetRegions( in_image->GetLargestPossibleRegion() ) ;
  out_image->SetSpacing( in_image->GetSpacing() ) ;
  out_image->SetOrigin( in_image->GetOrigin() ) ;
  out_image->SetDirection( in_image->GetDirection() );
  //out_image->CopyInformation( in_image );
  out_image->Allocate() ;

  itk::ImageRegionConstIterator< InImageType > in_iterator( in_image , in_image->GetLargestPossibleRegion() ) ;
  itk::ImageRegionIterator< OutImageType > out_iterator( out_image , out_image->GetLargestPossibleRegion() ) ;
  for( in_iterator.GoToBegin() , out_iterator.GoToBegin() ; !in_iterator.IsAtEnd() ; ++in_iterator , ++out_iterator )
    {
    out_iterator.Set( static_cast< typename OutImageType::PixelType >( in_iterator.Get() ) ) ;
    }
  return wrap< OutImageType >( out_image );
}

template <typename InImageType, typename OutImageType>
void wrapantsImageClone(py::module & m, std::string const & suffix) {
  m.def(("antsImageClone"+suffix).c_str(), &antsImageClone<InImageType,OutImageType>);
}
//pixels: Image, VectorImage
//types: unsigned char, unsigned int, float, double
//dims: 2, 3, 4
PYBIND11_MODULE(antsImageClone, m)
{
  // dim = 2
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<unsigned char,2>>(m, "UC2UC2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<unsigned int,2>>(m, "UC2UI2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<float,2>>(m, "UC2F2");
  wrapantsImageClone<itk::Image<unsigned char,2>,itk::Image<double,2>>(m, "UC2D2");

  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<unsigned char,2>>(m, "UI2UC2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<unsigned int,2>>(m, "UI2UI2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<float,2>>(m, "UI2F2");
  wrapantsImageClone<itk::Image<unsigned int,2>,itk::Image<double,2>>(m, "UI2D2");

  wrapantsImageClone<itk::Image<float,2>,itk::Image<unsigned char,2>>(m, "F2UC2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<unsigned int,2>>(m, "F2UI2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<float,2>>(m, "F2F2");
  wrapantsImageClone<itk::Image<float,2>,itk::Image<double,2>>(m, "F2D2");

  wrapantsImageClone<itk::Image<double,2>,itk::Image<unsigned char,2>>(m, "D2UC2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<unsigned int,2>>(m, "D2UI2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<float,2>>(m, "D2F2");
  wrapantsImageClone<itk::Image<double,2>,itk::Image<double,2>>(m, "D2D2");

  // dim = 3
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<unsigned char,3>>(m, "UC3UC2");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<unsigned int,3>>(m, "UC3UI3");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<float,3>>(m, "UC3F3");
  wrapantsImageClone<itk::Image<unsigned char,3>,itk::Image<double,3>>(m, "UC3D3");

  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<unsigned char,3>>(m, "UI3UC3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<unsigned int,3>>(m, "UI3UI3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<float,3>>(m, "UI3F3");
  wrapantsImageClone<itk::Image<unsigned int,3>,itk::Image<double,3>>(m, "UI3D3");

  wrapantsImageClone<itk::Image<float,3>,itk::Image<unsigned char,3>>(m, "F3UC3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<unsigned int,3>>(m, "F3UI3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<float,3>>(m, "F3F3");
  wrapantsImageClone<itk::Image<float,3>,itk::Image<double,3>>(m, "F3D3");

  wrapantsImageClone<itk::Image<double,3>,itk::Image<unsigned char,3>>(m, "D3UC3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<unsigned int,3>>(m, "D3UI3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<float,3>>(m, "D3F3");
  wrapantsImageClone<itk::Image<double,3>,itk::Image<double,3>>(m, "D3D3");

  // dim = 4
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<unsigned char,4>>(m, "UC4UC4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<unsigned int,4>>(m, "UC4UI4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<float,4>>(m, "UC4F4");
  wrapantsImageClone<itk::Image<unsigned char,4>,itk::Image<double,4>>(m, "UC4D4");

  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<unsigned char,4>>(m, "UI4UC4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<unsigned int,4>>(m, "UI4UI4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<float,4>>(m, "UI4F4");
  wrapantsImageClone<itk::Image<unsigned int,4>,itk::Image<double,4>>(m, "UI4D4");

  wrapantsImageClone<itk::Image<float,4>,itk::Image<unsigned char,4>>(m, "F4UC4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<unsigned int,4>>(m, "F4UI4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<float,4>>(m, "F4F4");
  wrapantsImageClone<itk::Image<float,4>,itk::Image<double,4>>(m, "F4D4");

  wrapantsImageClone<itk::Image<double,4>,itk::Image<unsigned char,4>>(m, "D4UC4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<unsigned int,4>>(m, "D4UI4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<float,4>>(m, "D4F4");
  wrapantsImageClone<itk::Image<double,4>,itk::Image<double,4>>(m, "D4D4");

  // VectorImage
  // dim = 2
  wrapantsImageClone<itk::VectorImage<unsigned char,2>,itk::VectorImage<unsigned char,2>>(m, "VUC2VUC2");
  wrapantsImageClone<itk::VectorImage<unsigned char,2>,itk::VectorImage<unsigned int,2>>(m, "VUC2VUI2");
  wrapantsImageClone<itk::VectorImage<unsigned char,2>,itk::VectorImage<float,2>>(m, "VUC2VF2");
  wrapantsImageClone<itk::VectorImage<unsigned char,2>,itk::VectorImage<double,2>>(m, "UC2D2");

  wrapantsImageClone<itk::VectorImage<unsigned int,2>,itk::VectorImage<unsigned char,2>>(m, "UI2UC2");
  wrapantsImageClone<itk::VectorImage<unsigned int,2>,itk::VectorImage<unsigned int,2>>(m, "UI2UI2");
  wrapantsImageClone<itk::VectorImage<unsigned int,2>,itk::VectorImage<float,2>>(m, "UI2F2");
  wrapantsImageClone<itk::VectorImage<unsigned int,2>,itk::VectorImage<double,2>>(m, "UI2D2");

  wrapantsImageClone<itk::VectorImage<float,2>,itk::VectorImage<unsigned char,2>>(m, "F2UC2");
  wrapantsImageClone<itk::VectorImage<float,2>,itk::VectorImage<unsigned int,2>>(m, "F2UI2");
  wrapantsImageClone<itk::VectorImage<float,2>,itk::VectorImage<float,2>>(m, "F2F2");
  wrapantsImageClone<itk::VectorImage<float,2>,itk::VectorImage<double,2>>(m, "F2D2");

  wrapantsImageClone<itk::VectorImage<double,2>,itk::VectorImage<unsigned char,2>>(m, "D2UC2");
  wrapantsImageClone<itk::VectorImage<double,2>,itk::VectorImage<unsigned int,2>>(m, "D2UI2");
  wrapantsImageClone<itk::VectorImage<double,2>,itk::VectorImage<float,2>>(m, "D2F2");
  wrapantsImageClone<itk::VectorImage<double,2>,itk::VectorImage<double,2>>(m, "D2D2");

  // dim = 3
  wrapantsImageClone<itk::VectorImage<unsigned char,3>,itk::VectorImage<unsigned char,3>>(m, "UC3UC2");
  wrapantsImageClone<itk::VectorImage<unsigned char,3>,itk::VectorImage<unsigned int,3>>(m, "UC3UI3");
  wrapantsImageClone<itk::VectorImage<unsigned char,3>,itk::VectorImage<float,3>>(m, "UC3F3");
  wrapantsImageClone<itk::VectorImage<unsigned char,3>,itk::VectorImage<double,3>>(m, "UC3D3");

  wrapantsImageClone<itk::VectorImage<unsigned int,3>,itk::VectorImage<unsigned char,3>>(m, "UI3UC3");
  wrapantsImageClone<itk::VectorImage<unsigned int,3>,itk::VectorImage<unsigned int,3>>(m, "UI3UI3");
  wrapantsImageClone<itk::VectorImage<unsigned int,3>,itk::VectorImage<float,3>>(m, "UI3F3");
  wrapantsImageClone<itk::VectorImage<unsigned int,3>,itk::VectorImage<double,3>>(m, "UI3D3");

  wrapantsImageClone<itk::VectorImage<float,3>,itk::VectorImage<unsigned char,3>>(m, "F3UC3");
  wrapantsImageClone<itk::VectorImage<float,3>,itk::VectorImage<unsigned int,3>>(m, "F3UI3");
  wrapantsImageClone<itk::VectorImage<float,3>,itk::VectorImage<float,3>>(m, "F3F3");
  wrapantsImageClone<itk::VectorImage<float,3>,itk::VectorImage<double,3>>(m, "F3D3");

  wrapantsImageClone<itk::VectorImage<double,3>,itk::VectorImage<unsigned char,3>>(m, "D3UC3");
  wrapantsImageClone<itk::VectorImage<double,3>,itk::VectorImage<unsigned int,3>>(m, "D3UI3");
  wrapantsImageClone<itk::VectorImage<double,3>,itk::VectorImage<float,3>>(m, "D3F3");
  wrapantsImageClone<itk::VectorImage<double,3>,itk::VectorImage<double,3>>(m, "D3D3");

  // dim = 4
  wrapantsImageClone<itk::VectorImage<unsigned char,4>,itk::VectorImage<unsigned char,4>>(m, "UC4UC4");
  wrapantsImageClone<itk::VectorImage<unsigned char,4>,itk::VectorImage<unsigned int,4>>(m, "UC4UI4");
  wrapantsImageClone<itk::VectorImage<unsigned char,4>,itk::VectorImage<float,4>>(m, "UC4F4");
  wrapantsImageClone<itk::VectorImage<unsigned char,4>,itk::VectorImage<double,4>>(m, "UC4D4");

  wrapantsImageClone<itk::VectorImage<unsigned int,4>,itk::VectorImage<unsigned char,4>>(m, "UI4UC4");
  wrapantsImageClone<itk::VectorImage<unsigned int,4>,itk::VectorImage<unsigned int,4>>(m, "UI4UI4");
  wrapantsImageClone<itk::VectorImage<unsigned int,4>,itk::VectorImage<float,4>>(m, "UI4F4");
  wrapantsImageClone<itk::VectorImage<unsigned int,4>,itk::VectorImage<double,4>>(m, "UI4D4");

  wrapantsImageClone<itk::VectorImage<float,4>,itk::VectorImage<unsigned char,4>>(m, "F4UC4");
  wrapantsImageClone<itk::VectorImage<float,4>,itk::VectorImage<unsigned int,4>>(m, "F4UI4");
  wrapantsImageClone<itk::VectorImage<float,4>,itk::VectorImage<float,4>>(m, "F4F4");
  wrapantsImageClone<itk::VectorImage<float,4>,itk::VectorImage<double,4>>(m, "F4D4");

  wrapantsImageClone<itk::VectorImage<double,4>,itk::VectorImage<unsigned char,4>>(m, "D4UC4");
  wrapantsImageClone<itk::VectorImage<double,4>,itk::VectorImage<unsigned int,4>>(m, "D4UI4");
  wrapantsImageClone<itk::VectorImage<double,4>,itk::VectorImage<float,4>>(m, "D4F4");
  wrapantsImageClone<itk::VectorImage<double,4>,itk::VectorImage<double,4>>(m, "D4D4");

  // vector image, dim = 2

}

<|endoftext|>


<commit_before>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"
using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Function &F, StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (CalledFunction && CalledFunction->hasName() &&
            CalledFunction->isDeclaration() &&
            !CalledFunctions.count(CalledFunction->getName())) {
          CalledFunctions.insert(CalledFunction->getName());
          Worklist.push_back(CalledFunction->getName());
        }
      }
    }
  }
}

// Helper function: given a worklist and an index, will process all the worklist
// and import them based on the summary information
static unsigned ProcessImportWorklist(
    Module &DestModule, SmallVector<StringRef, 64> &Worklist,
    StringSet<> &CalledFunctions, Linker &TheLinker,
    const FunctionInfoIndex &Index,
    std::function<std::unique_ptr<Module>(StringRef FileName)> &
        LazyModuleLoader) {
  unsigned ImportCount = 0;
  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << DestModule.getModuleIdentifier() << "Process import for "
                 << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier() << "No summary for "
                   << CalledFunctionName << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << DestModule.getModuleIdentifier()
                   << " Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier() << " Skip import of "
                   << CalledFunctionName << " with " << Summary->instCount()
                   << " instructions (limit " << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto FileName = Summary->modulePath();
    DEBUG(dbgs() << "Importing " << CalledFunctionName << " from " << FileName
                 << "\n");

    // Get the module for the import
    auto SrcModule = LazyModuleLoader(FileName);
    assert(&SrcModule->getContext() == &DestModule.getContext());

    // The function that we will import!
    GlobalValue *SGV = SrcModule->getNamedValue(CalledFunctionName);
    StringRef ImportFunctionName = CalledFunctionName;
    if (!SGV) {
      // Might be local in source Module, promoted/renamed in DestModule.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = SrcModule->getNamedValue(Split.first);
#ifndef NDEBUG
      // Assert that Split.second is module id
      uint64_t ModuleId;
      assert(!Split.second.getAsInteger(10, ModuleId));
      assert(ModuleId == Index.getModuleId(FileName));
#endif
    }
    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      ImportFunctionName = F->getName();
    }
    if (!F) {
      errs() << "Can't load function '" << CalledFunctionName << "' in Module '"
             << FileName << "', error in the summary?\n";
      llvm_unreachable("Can't load function in Module");
    }

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier()
                   << " Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from " << FileName << "\n");
      continue;
    }

    // Link in the specified function.
    DenseSet<const GlobalValue *> FunctionsToImport;
    FunctionsToImport.insert(F);
    if (TheLinker.linkInModule(*SrcModule, Linker::Flags::None, &Index,
                               &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    // Process the newly imported function and add callees to the worklist.
    GlobalValue *NewGV = DestModule.getNamedValue(ImportFunctionName);
    assert(NewGV);
    Function *NewF = dyn_cast<Function>(NewGV);
    assert(NewF);
    findExternalCalls(*NewF, CalledFunctions, Worklist);
    ++ImportCount;
  }
  return ImportCount;
}

// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &DestModule) {
  DEBUG(dbgs() << "Starting import for Module "
               << DestModule.getModuleIdentifier() << "\n");
  unsigned ImportedCount = 0;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : DestModule) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(F, CalledFunctions, Worklist);
  }
  if (Worklist.empty())
    return false;

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker TheLinker(DestModule, DiagnosticHandler);

  ImportedCount += ProcessImportWorklist(DestModule, Worklist, CalledFunctions,
                                         TheLinker, Index, ModuleLoader);

  DEBUG(errs() << "Imported " << ImportedCount << " functions for Module "
               << DestModule.getModuleIdentifier() << "\n");
  return ImportedCount;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {
  /// Optional function summary index to use for importing, otherwise
  /// the summary-file option must be specified.
  FunctionInfoIndex *Index;

public:
  /// Pass identification, replacement for typeid
  static char ID;

  /// Specify pass name for debug output
  const char *getPassName() const override {
    return "Function Importing";
  }

  explicit FunctionImportPass(FunctionInfoIndex *Index = nullptr)
      : ModulePass(ID), Index(Index) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty() && !Index)
      report_fatal_error("error: -function-import requires -summary-file or "
                         "file from frontend\n");
    std::unique_ptr<FunctionInfoIndex> IndexPtr;
    if (!SummaryFile.empty()) {
      if (Index)
        report_fatal_error("error: -summary-file and index from frontend\n");
      std::string Error;
      IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
      if (!IndexPtr) {
        errs() << "Error loading file '" << SummaryFile << "': " << Error
               << "\n";
        return false;
      }
      Index = IndexPtr.get();
    }

    // Perform the import now.
    auto ModuleLoader = [&M](StringRef Identifier) {
      return loadFile(Identifier, M.getContext());
    };
    FunctionImporter Importer(*Index, diagnosticHandler, ModuleLoader);
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass(FunctionInfoIndex *Index = nullptr) {
  return new FunctionImportPass(Index);
}
}
<commit_msg>The current importing scheme is processing one function at a time, loading the source Module, linking the function in the destination module, and destroying the source Module before repeating with the next function to import (potentially from the same Module).<commit_after>//===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Function import based on summaries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/FunctionImport.h"

#include "llvm/ADT/StringSet.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Object/FunctionIndexObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/SourceMgr.h"

#include <map>

using namespace llvm;

#define DEBUG_TYPE "function-import"

/// Limit on instruction count of imported functions.
static cl::opt<unsigned> ImportInstrLimit(
    "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
    cl::desc("Only import functions with less than N instructions"));

// Load lazily a module from \p FileName in \p Context.
static std::unique_ptr<Module> loadFile(const std::string &FileName,
                                        LLVMContext &Context) {
  SMDiagnostic Err;
  DEBUG(dbgs() << "Loading '" << FileName << "'\n");
  std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context);
  if (!Result) {
    Err.print("function-import", errs());
    return nullptr;
  }

  Result->materializeMetadata();
  UpgradeDebugInfo(*Result);

  return Result;
}

namespace {
/// Helper to load on demand a Module from file and cache it for subsequent
/// queries. It can be used with the FunctionImporter.
class ModuleLazyLoaderCache {
  /// Cache of lazily loaded module for import.
  StringMap<std::unique_ptr<Module>> ModuleMap;

  /// Retrieve a Module from the cache or lazily load it on demand.
  std::function<std::unique_ptr<Module>(StringRef FileName)> createLazyModule;

public:
  /// Create the loader, Module will be initialized in \p Context.
  ModuleLazyLoaderCache(std::function<
      std::unique_ptr<Module>(StringRef FileName)> createLazyModule)
      : createLazyModule(createLazyModule) {}

  /// Retrieve a Module from the cache or lazily load it on demand.
  Module &operator()(StringRef FileName);
};

// Get a Module for \p FileName from the cache, or load it lazily.
Module &ModuleLazyLoaderCache::operator()(StringRef Identifier) {
  auto &Module = ModuleMap[Identifier];
  if (!Module)
    Module = createLazyModule(Identifier);
  return *Module;
}
} // anonymous namespace

/// Walk through the instructions in \p F looking for external
/// calls not already in the \p CalledFunctions set. If any are
/// found they are added to the \p Worklist for importing.
static void findExternalCalls(const Module &DestModule, Function &F,
                              const FunctionInfoIndex &Index,
                              StringSet<> &CalledFunctions,
                              SmallVector<StringRef, 64> &Worklist) {
  // We need to suffix internal function calls imported from other modules,
  // prepare the suffix ahead of time.
  StringRef Suffix;
  if (F.getParent() != &DestModule)
    Suffix =
        (Twine(".llvm.") +
         Twine(Index.getModuleId(F.getParent()->getModuleIdentifier()))).str();

  for (auto &BB : F) {
    for (auto &I : BB) {
      if (isa<CallInst>(I)) {
        auto CalledFunction = cast<CallInst>(I).getCalledFunction();
        // Insert any new external calls that have not already been
        // added to set/worklist.
        if (!CalledFunction || !CalledFunction->hasName())
          continue;
        // Ignore intrinsics early
        if (CalledFunction->isIntrinsic()) {
          assert(CalledFunction->getIntrinsicID() != 0);
          continue;
        }
        auto ImportedName = CalledFunction->getName();
        auto Renamed = (ImportedName + Suffix).str();
        // Rename internal functions
        if (CalledFunction->hasInternalLinkage()) {
          ImportedName = Renamed;
        }
        auto It = CalledFunctions.insert(ImportedName);
        if (!It.second) {
          // This is a call to a function we already considered, skip.
          continue;
        }
        // Ignore functions already present in the destination module
        auto *SrcGV = DestModule.getNamedValue(ImportedName);
        if (SrcGV) {
          assert(isa<Function>(SrcGV) && "Name collision during import");
          if (!cast<Function>(SrcGV)->isDeclaration()) {
            DEBUG(dbgs() << DestModule.getModuleIdentifier() << "Ignoring "
                         << ImportedName << " already in DestinationModule\n");
            continue;
          }
        }

        Worklist.push_back(It.first->getKey());
        DEBUG(dbgs() << DestModule.getModuleIdentifier()
                     << " Adding callee for : " << ImportedName << " : "
                     << F.getName() << "\n");
      }
    }
  }
}

// Helper function: given a worklist and an index, will process all the worklist
// and decide what to import based on the summary information.
//
// Nothing is actually imported, functions are materialized in their source
// module and analyzed there.
//
// \p ModuleToFunctionsToImportMap is filled with the set of Function to import
// per Module.
static void GetImportList(
    Module &DestModule, SmallVector<StringRef, 64> &Worklist,
    StringSet<> &CalledFunctions,
    std::map<StringRef, std::pair<Module *, DenseSet<const GlobalValue *>>> &
        ModuleToFunctionsToImportMap,
    const FunctionInfoIndex &Index, ModuleLazyLoaderCache &ModuleLoaderCache) {
  while (!Worklist.empty()) {
    auto CalledFunctionName = Worklist.pop_back_val();
    DEBUG(dbgs() << DestModule.getModuleIdentifier() << "Process import for "
                 << CalledFunctionName << "\n");

    // Try to get a summary for this function call.
    auto InfoList = Index.findFunctionInfoList(CalledFunctionName);
    if (InfoList == Index.end()) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier() << "No summary for "
                   << CalledFunctionName << " Ignoring.\n");
      continue;
    }
    assert(!InfoList->second.empty() && "No summary, error at import?");

    // Comdat can have multiple entries, FIXME: what do we do with them?
    auto &Info = InfoList->second[0];
    assert(Info && "Nullptr in list, error importing summaries?\n");

    auto *Summary = Info->functionSummary();
    if (!Summary) {
      // FIXME: in case we are lazyloading summaries, we can do it now.
      DEBUG(dbgs() << DestModule.getModuleIdentifier()
                   << " Missing summary for  " << CalledFunctionName
                   << ", error at import?\n");
      llvm_unreachable("Missing summary");
    }

    if (Summary->instCount() > ImportInstrLimit) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier() << " Skip import of "
                   << CalledFunctionName << " with " << Summary->instCount()
                   << " instructions (limit " << ImportInstrLimit << ")\n");
      continue;
    }

    // Get the module path from the summary.
    auto ModuleIdentifier = Summary->modulePath();
    DEBUG(dbgs() << DestModule.getModuleIdentifier() << " Importing "
                 << CalledFunctionName << " from " << ModuleIdentifier << "\n");

    auto &SrcModule = ModuleLoaderCache(ModuleIdentifier);

    // The function that we will import!
    GlobalValue *SGV = SrcModule.getNamedValue(CalledFunctionName);

    if (!SGV) {
      // The destination module is referencing function using their renamed name
      // when importing a function that was originally local in the source
      // module. The source module we have might not have been renamed so we try
      // to remove the suffix added during the renaming to recover the original
      // name in the source module.
      std::pair<StringRef, StringRef> Split =
          CalledFunctionName.split(".llvm.");
      SGV = SrcModule.getNamedValue(Split.first);
      assert(SGV && "Can't find function to import in source module");
    }
    if (!SGV) {
      report_fatal_error(Twine("Can't load function '") + CalledFunctionName +
                         "' in Module '" + SrcModule.getModuleIdentifier() +
                         "', error in the summary?\n");
    }

    Function *F = dyn_cast<Function>(SGV);
    if (!F && isa<GlobalAlias>(SGV)) {
      auto *SGA = dyn_cast<GlobalAlias>(SGV);
      F = dyn_cast<Function>(SGA->getBaseObject());
      CalledFunctionName = F->getName();
    }
    assert(F && "Imported Function is ... not a Function");

    // We cannot import weak_any functions/aliases without possibly affecting
    // the order they are seen and selected by the linker, changing program
    // semantics.
    if (SGV->hasWeakAnyLinkage()) {
      DEBUG(dbgs() << DestModule.getModuleIdentifier()
                   << " Ignoring import request for weak-any "
                   << (isa<Function>(SGV) ? "function " : "alias ")
                   << CalledFunctionName << " from "
                   << SrcModule.getModuleIdentifier() << "\n");
      continue;
    }

    // Add the function to the import list
    auto &Entry = ModuleToFunctionsToImportMap[SrcModule.getModuleIdentifier()];
    Entry.first = &SrcModule;
    Entry.second.insert(F);

    // Process the newly imported functions and add callees to the worklist.
    F->materialize();
    findExternalCalls(DestModule, *F, Index, CalledFunctions, Worklist);
  }
}

// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
// The current implementation imports every called functions that exists in the
// summaries index.
bool FunctionImporter::importFunctions(Module &DestModule) {
  DEBUG(dbgs() << "Starting import for Module "
               << DestModule.getModuleIdentifier() << "\n");
  unsigned ImportedCount = 0;

  /// First step is collecting the called external functions.
  StringSet<> CalledFunctions;
  SmallVector<StringRef, 64> Worklist;
  for (auto &F : DestModule) {
    if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone))
      continue;
    findExternalCalls(DestModule, F, Index, CalledFunctions, Worklist);
  }
  if (Worklist.empty())
    return false;

  /// Second step: for every call to an external function, try to import it.

  // Linker that will be used for importing function
  Linker TheLinker(DestModule, DiagnosticHandler);

  // Map of Module -> List of Function to import from the Module
  std::map<StringRef, std::pair<Module *, DenseSet<const GlobalValue *>>>
      ModuleToFunctionsToImportMap;

  // Analyze the summaries and get the list of functions to import by
  // populating ModuleToFunctionsToImportMap
  ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader);
  GetImportList(DestModule, Worklist, CalledFunctions,
                ModuleToFunctionsToImportMap, Index, ModuleLoaderCache);
  assert(Worklist.empty() && "Worklist hasn't been flushed in GetImportList");

  // Do the actual import of functions now, one Module at a time
  for (auto &FunctionsToImportPerModule : ModuleToFunctionsToImportMap) {
    // Get the module for the import
    auto &FunctionsToImport = FunctionsToImportPerModule.second.second;
    auto *SrcModule = FunctionsToImportPerModule.second.first;
    assert(&DestModule.getContext() == &SrcModule->getContext() &&
           "Context mismatch");

    // Link in the specified functions.
    if (TheLinker.linkInModule(*SrcModule, Linker::Flags::None, &Index,
                               &FunctionsToImport))
      report_fatal_error("Function Import: link error");

    ImportedCount += FunctionsToImport.size();
  }
  DEBUG(dbgs() << "Imported " << ImportedCount << " functions for Module "
               << DestModule.getModuleIdentifier() << "\n");
  return ImportedCount;
}

/// Summary file to use for function importing when using -function-import from
/// the command line.
static cl::opt<std::string>
    SummaryFile("summary-file",
                cl::desc("The summary file to use for function importing."));

static void diagnosticHandler(const DiagnosticInfo &DI) {
  raw_ostream &OS = errs();
  DiagnosticPrinterRawOStream DP(OS);
  DI.print(DP);
  OS << '\n';
}

/// Parse the function index out of an IR file and return the function
/// index object if found, or nullptr if not.
static std::unique_ptr<FunctionInfoIndex>
getFunctionIndexForFile(StringRef Path, std::string &Error,
                        DiagnosticHandlerFunction DiagnosticHandler) {
  std::unique_ptr<MemoryBuffer> Buffer;
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFile(Path);
  if (std::error_code EC = BufferOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  Buffer = std::move(BufferOrErr.get());
  ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr =
      object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(),
                                              DiagnosticHandler);
  if (std::error_code EC = ObjOrErr.getError()) {
    Error = EC.message();
    return nullptr;
  }
  return (*ObjOrErr)->takeIndex();
}

/// Pass that performs cross-module function import provided a summary file.
class FunctionImportPass : public ModulePass {
  /// Optional function summary index to use for importing, otherwise
  /// the summary-file option must be specified.
  FunctionInfoIndex *Index;

public:
  /// Pass identification, replacement for typeid
  static char ID;

  /// Specify pass name for debug output
  const char *getPassName() const override {
    return "Function Importing";
  }

  explicit FunctionImportPass(FunctionInfoIndex *Index = nullptr)
      : ModulePass(ID), Index(Index) {}

  bool runOnModule(Module &M) override {
    if (SummaryFile.empty() && !Index)
      report_fatal_error("error: -function-import requires -summary-file or "
                         "file from frontend\n");
    std::unique_ptr<FunctionInfoIndex> IndexPtr;
    if (!SummaryFile.empty()) {
      if (Index)
        report_fatal_error("error: -summary-file and index from frontend\n");
      std::string Error;
      IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler);
      if (!IndexPtr) {
        errs() << "Error loading file '" << SummaryFile << "': " << Error
               << "\n";
        return false;
      }
      Index = IndexPtr.get();
    }

    // Perform the import now.
    auto ModuleLoader = [&M](StringRef Identifier) {
      return loadFile(Identifier, M.getContext());
    };
    FunctionImporter Importer(*Index, diagnosticHandler, ModuleLoader);
    return Importer.importFunctions(M);

    return false;
  }
};

char FunctionImportPass::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import",
                      "Summary Based Function Import", false, false)
INITIALIZE_PASS_END(FunctionImportPass, "function-import",
                    "Summary Based Function Import", false, false)

namespace llvm {
Pass *createFunctionImportPass(FunctionInfoIndex *Index = nullptr) {
  return new FunctionImportPass(Index);
}
}
<|endoftext|>


<commit_before>#include "classui.h"
#include "listworker.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <time.h>

using namespace std;

ClassUI::ClassUI()
{

}

void ClassUI::run()
{

    cout << "\t" << "Welcome to the Amazing Database! " << endl;
    cout << "-----------------------------------------------------------" << endl;
    cout << "\t" << "   *** Quote of the day ***" << endl;
    cout << getQuotes() << endl;
    mainMenu();
}
void ClassUI::mainMenu()
{
    string choice;
    do
    {

        cout << "-----------------------------------------------------------" << endl;
        cout << " (1) - Add" << "\t" << "Add a person to the database." << endl;
        cout << " (2) - Remove" << "\t" << "Remove a person from the database." << endl;
        cout << " (3) - View" << "\t" << "View the entire database." << endl;
        cout << " (4) - Save" << "\t" << "Save the database." << endl;
        cout << " (5) - Search" << "\t" << "Search the database." << endl;
        cout << " (6) - Sort" << "\t" << "Sort the database." << endl;
        cout << " (7) - Exit" << "\t" << "Exit." << endl;

        cout << "Enter your command (1 - 7): ";
        cin >> choice;
        cout << endl;

        if (choice != "7")
        {
           select(choice);
        }
        else{
            list.saveFile();
            runOn = false;
        }
    }while(runOn == true);
}

void ClassUI::select(string ch)
{
    if(ch == "1")
    {
        addPerson();
    }

    else if(ch == "3")
    {
        viewAll();
    }
    else if(ch == "6")
    {
        string sortcho;
        cout << "Enter a sort command (1 - 3):" << endl;
        cout << "------------------------" << endl;
        cout << " (1) - Sort by alphabetical order" << endl;
        cout << " (2) - Sort by chronological order" << endl;
        cout << " (3) - Return to main menu" << endl;
        cout << "Enter your command (1 - 2): ";
        cin >> sortcho;
        cout << endl;

        if(sortcho == "1")
        {
            list.sortNames();
             viewAll();
        }
        else if(sortcho == "2")
        {
            list.sortBirth();
             viewAll();
        }
        else if(sortcho == "3")
        {
            mainMenu();
        }

    }
    else if(ch == "5")
    {
        searching();
    }
    else if(ch == "2")
    {
        remove();
    }
    else if(ch == "4")
    {
        save();
    }
    else if(ch == "8")
    {
        yo();
    }
    else
    {
        cout << "Invalid input. Please enter a number between 1 - 7." << endl;
    }
}
void ClassUI::view(int i)
{
    int nameSize  = list.getNameSize(i);
    cout << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "Name" << "\t" << "\t" << "\t" << "\t" << "|Gender " << "|Born " << "\t" << "|Death" << endl;
    cout << "--------------------------------|-------|-------|-------------" << endl;

    cout << list.getName(i);
    if(nameSize > 0 && nameSize <= 7)
    {
        cout << "\t" << "\t" << "\t" << "\t";
    }
    else if(nameSize > 7 && nameSize <= 15)
    {
        cout << "\t" << "\t" << "\t";
    }
    else if(nameSize > 15 && nameSize <= 23)
    {
        cout << "\t" << "\t";
    }
    else if(nameSize > 23 && nameSize <= 31)
    {
        cout << "\t";
    }

    if(list.getGender(i) == 'M' || list.getGender(i) == 'm')
    {
        cout << "|Male" << "\t";
    }
    else
    {
        cout << "|Female" << "\t";
    }
    cout  << "|" << list.getBirth(i);
    if(list.getDeath(i) == 0)
    {
        cout << "\t" << "| n/a"  << endl;
    }
    else
    {
        cout << "\t" << "|" << list.getDeath(i)  << endl;
    }
    cout << list.getComment(i) << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << endl;
}

void ClassUI::searching()
{

    cout << "----------Select any of the following commands----------" << endl;
    cout << "What do you want to search for? (1 - 4)" << endl;
    cout << " (1) - Searches for a name." << endl;
    cout << " (2) - Searches for a Gender." << endl;
    cout << " (3) - Searches for a year born." << endl;
    cout << " (4) - Return to main menu" << endl;

    search();
}
void ClassUI::addPerson()
{
    string name;
    char gender;
    char yesOrNo;
    int yearOfBirth = 0;
    int yearOfDeath = 0;
    string comment;

    cout << "Input Name: ";
    cin.ignore();
    std::getline(std::cin,name);
    cout << "Input gender (M/F): ";
    cin >> gender;
    if (gender == 'm')
    {
        gender = 'M';
    }
    else if (gender == 'f')
    {
        gender = 'F';
    }
    if (gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
    {
       cout << "Input year of birth: ";
       cin >> yearOfBirth;

       cout << "Is the individual deceased? (y/n)";
       cin >> yesOrNo;
       if (yesOrNo == 'Y' || yesOrNo == 'y')
       {
            cout << "Input year of death: ";
            cin >> yearOfDeath;
       }
        cout << "Input a comment about the individual: ";
        cin.ignore();
        std::getline(std::cin,comment);
    }
    else
    {
        cout << "Invalid gender! Try again." << endl;
        addPerson();
    }
    cout << "Are you sure that you want to add this person? yes or no: "; // Þetta er ógeðslegur texti, endilega finnum eitthvað skárra
    string validatePerson;
    cin >> validatePerson;
    if(validatePerson == "yes")
    {
        cout << "New person added!" << endl;
        list.addNewPerson(name, gender, yearOfBirth, yearOfDeath, comment);
    }
    else
    {
        cout << "Operation addPerson aborted!" << endl; // Endilega komið með tillögu að breytingu á þessum texta
    }
}

void ClassUI::search()
{
    string searchChoice;
    cout << "Enter your command (1 - 4): ";
    cin >> searchChoice;
    if (searchChoice == "1")
    {

        string namesearch;
        cout << "Enter a name you want to search for: ";
        cin.ignore();
        std::getline(std::cin,namesearch);

        for(int i = 0; i < list.getPersonsSize();++i)
        {
            std::size_t found = list.getName(i).find(namesearch);
            if (found!=std::string::npos)
            {
                view(i);
            }

        }
        if(list.nameSearcher(namesearch) == false)
        {
            cout << "Sorry that name is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
            searching();
        }
    }
    else if (searchChoice == "2")
    {
        char gendersearch;

        cout << "Enter a gender you want to search for: (M/F)";
        cin >> gendersearch;
        if(gendersearch == 'm')
            {
                 gendersearch = 'M';
            }
        else if (gendersearch == 'f')
            {
                 gendersearch = 'F';
            }

        for(int i = 0; i < list.getPersonsSize();++i)
        {
            if(gendersearch == list.getGender(i))
            {
                gendersearch = list.getGender(i);
                view(i);
            }
        }
        if(list.genderSearcher(gendersearch) == false)
        {
            cout << "Sorry that gender is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
            searching();
        }
    }
    else if (searchChoice == "3")
    {
            int yearsearch;
            cout << "Enter a year you want to search for: ";
            cin >> yearsearch;

            for(int i = 0; i < list.getPersonsSize();++i)
            {
                if(yearsearch == list.getBirth(i))
                {
                    yearsearch = list.getBirth(i);
                    view(i);
                }
            }
            if(list.yearSearcher(yearsearch) == false)
            {
                cout << "Sorry that year is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
                searching();
            }
    }
    else if (searchChoice == "4")
    {
        mainMenu();
    }
    else
    {
        cout << "Error reading input. Please enter a number between 1- 3." << endl;
        search();
    }
}
void ClassUI::remove()
{
    string name;
    cout << "Enter the full name of the person that you want to remove: ";
    cin.ignore();
    std::getline(std::cin,name);
    if (list.removePersonFound(name) == true)
    {
        char validateRemove;
        cout << "Person found!" << endl;
        cout << "Are you sure you want to remove this person? (y/n): ";
        cin >> validateRemove;

        if(validateRemove == 'y' || validateRemove == 'Y')
        {
            if(list.removePerson(name) == true)
            {
                cout << "Person removed!" << endl;
            }
            else
            {
                cout << "Person not removed!" << endl;
            }
        }

    }
    else
    {
        cout << "Person not found!" << endl;
    }
}
void ClassUI::save()
{
    list.saveFile();
}
void ClassUI::viewAll()
{
    for(int i = 0; i < list.getPersonsSize(); i++)
    {
        view(i);
    }
}
void ClassUI::yo()
{
    cout << endl;
    cout << "`8.`8888.      ,8'     ,o888888o.     " << endl;
    cout << " `8.`8888.    ,8'   . 8888     `88.   " << endl;
    cout << "  `8.`8888.  ,8'   ,8 8888       `8b  " << endl;
    cout << "   `8.`8888.,8'    88 8888        `8b " << endl;
    cout << "    `8.`88888'     88 8888         88 " << endl;
    cout << "     `8. 8888      88 8888         88 " << endl;
    cout << "      `8 8888      88 8888        ,8P " << endl;
    cout << "       8 8888      `8 8888       ,8P  " << endl;
    cout << "       8 8888       ` 8888     ,88'   " << endl;
    cout << "       8 8888          `8888888P'     " << endl;
    cout << endl;
}

string ClassUI::getQuotes()
{
    string quotes[5] = {"\"A good programmer is someone who always looks both ways before crossing a one-way street.\" (Doug Linder)",
                        "\"Programming is like sex. One mistake and you have to support it for the rest of your life.\" (Michael Sinz)",
                        "\"Walking on water and developing software from a specification are easy if both are frozen.\" (Edward V Berard)",
                        "\"One man's crappy software is another man's full time job.\" (Jessica Gaston)",
                        "\"A C program is like a fast dance on a newly waxed dance floor by people carrying razors.\" (Waldi Ravens)"
                       };
    int v1 = 0;
    srand (time(NULL));
    v1 = rand() % 5;
    return quotes[v1];
}
<commit_msg>Laga bandstrik i uppsetningu<commit_after>#include "classui.h"
#include "listworker.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <time.h>

using namespace std;

ClassUI::ClassUI()
{

}

void ClassUI::run()
{

    cout << "\t" << "Welcome to the Amazing Database! " << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "\t" << "   *** Quote of the day ***" << endl;
    cout << getQuotes() << endl;
    mainMenu();
}
void ClassUI::mainMenu()
{
    string choice;
    do
    {

        cout << "--------------------------------------------------------------" << endl;
        cout << " (1) - Add" << "\t" << "Add a person to the database." << endl;
        cout << " (2) - Remove" << "\t" << "Remove a person from the database." << endl;
        cout << " (3) - View" << "\t" << "View the entire database." << endl;
        cout << " (4) - Save" << "\t" << "Save the database." << endl;
        cout << " (5) - Search" << "\t" << "Search the database." << endl;
        cout << " (6) - Sort" << "\t" << "Sort the database." << endl;
        cout << " (7) - Exit" << "\t" << "Exit." << endl;

        cout << "Enter your command (1 - 7): ";
        cin >> choice;
        cout << endl;

        if (choice != "7")
        {
           select(choice);
        }
        else{
            list.saveFile();
            runOn = false;
        }
    }while(runOn == true);
}

void ClassUI::select(string ch)
{
    if(ch == "1")
    {
        addPerson();
    }

    else if(ch == "3")
    {
        viewAll();
    }
    else if(ch == "6")
    {
        string sortcho;
        cout << "Enter a sort command (1 - 3):" << endl;
        cout << "------------------------" << endl;
        cout << " (1) - Sort by alphabetical order" << endl;
        cout << " (2) - Sort by chronological order" << endl;
        cout << " (3) - Return to main menu" << endl;
        cout << "Enter your command (1 - 2): ";
        cin >> sortcho;
        cout << endl;

        if(sortcho == "1")
        {
            list.sortNames();
             viewAll();
        }
        else if(sortcho == "2")
        {
            list.sortBirth();
             viewAll();
        }
        else if(sortcho == "3")
        {
            mainMenu();
        }

    }
    else if(ch == "5")
    {
        searching();
    }
    else if(ch == "2")
    {
        remove();
    }
    else if(ch == "4")
    {
        save();
    }
    else if(ch == "8")
    {
        yo();
    }
    else
    {
        cout << "Invalid input. Please enter a number between 1 - 7." << endl;
    }
}
void ClassUI::view(int i)
{
    int nameSize  = list.getNameSize(i);
    cout << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << "Name" << "\t" << "\t" << "\t" << "\t" << "|Gender " << "|Born " << "\t" << "|Death" << endl;
    cout << "--------------------------------|-------|-------|-------------" << endl;

    cout << list.getName(i);
    if(nameSize > 0 && nameSize <= 7)
    {
        cout << "\t" << "\t" << "\t" << "\t";
    }
    else if(nameSize > 7 && nameSize <= 15)
    {
        cout << "\t" << "\t" << "\t";
    }
    else if(nameSize > 15 && nameSize <= 23)
    {
        cout << "\t" << "\t";
    }
    else if(nameSize > 23 && nameSize <= 31)
    {
        cout << "\t";
    }

    if(list.getGender(i) == 'M' || list.getGender(i) == 'm')
    {
        cout << "|Male" << "\t";
    }
    else
    {
        cout << "|Female" << "\t";
    }
    cout  << "|" << list.getBirth(i);
    if(list.getDeath(i) == 0)
    {
        cout << "\t" << "| n/a"  << endl;
    }
    else
    {
        cout << "\t" << "|" << list.getDeath(i)  << endl;
    }
    cout << list.getComment(i) << endl;
    cout << "--------------------------------------------------------------" << endl;
    cout << endl;
}

void ClassUI::searching()
{

    cout << "-------------Select any of the following commands-------------" << endl;
    cout << "What do you want to search for? (1 - 4)" << endl;
    cout << " (1) - Searches for a name." << endl;
    cout << " (2) - Searches for a Gender." << endl;
    cout << " (3) - Searches for a year born." << endl;
    cout << " (4) - Return to main menu" << endl;

    search();
}
void ClassUI::addPerson()
{
    string name;
    char gender;
    char yesOrNo;
    int yearOfBirth = 0;
    int yearOfDeath = 0;
    string comment;

    cout << "Input Name: ";
    cin.ignore();
    std::getline(std::cin,name);
    cout << "Input gender (M/F): ";
    cin >> gender;
    if (gender == 'm')
    {
        gender = 'M';
    }
    else if (gender == 'f')
    {
        gender = 'F';
    }
    if (gender == 'm' || gender == 'M' || gender == 'f' || gender == 'F')
    {
       cout << "Input year of birth: ";
       cin >> yearOfBirth;

       cout << "Is the individual deceased? (y/n)";
       cin >> yesOrNo;
       if (yesOrNo == 'Y' || yesOrNo == 'y')
       {
            cout << "Input year of death: ";
            cin >> yearOfDeath;
       }
        cout << "Input a comment about the individual: ";
        cin.ignore();
        std::getline(std::cin,comment);
    }
    else
    {
        cout << "Invalid gender! Try again." << endl;
        addPerson();
    }
    cout << "Are you sure that you want to add this person? yes or no: "; // Þetta er ógeðslegur texti, endilega finnum eitthvað skárra
    string validatePerson;
    cin >> validatePerson;
    if(validatePerson == "yes")
    {
        cout << "New person added!" << endl;
        list.addNewPerson(name, gender, yearOfBirth, yearOfDeath, comment);
    }
    else
    {
        cout << "Operation addPerson aborted!" << endl; // Endilega komið með tillögu að breytingu á þessum texta
    }
}

void ClassUI::search()
{
    string searchChoice;
    cout << "Enter your command (1 - 4): ";
    cin >> searchChoice;
    if (searchChoice == "1")
    {

        string namesearch;
        cout << "Enter a name you want to search for: ";
        cin.ignore();
        std::getline(std::cin,namesearch);

        for(int i = 0; i < list.getPersonsSize();++i)
        {
            std::size_t found = list.getName(i).find(namesearch);
            if (found!=std::string::npos)
            {
                view(i);
            }

        }
        if(list.nameSearcher(namesearch) == false)
        {
            cout << "Sorry that name is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
            searching();
        }
    }
    else if (searchChoice == "2")
    {
        char gendersearch;

        cout << "Enter a gender you want to search for: (M/F)";
        cin >> gendersearch;
        if(gendersearch == 'm')
            {
                 gendersearch = 'M';
            }
        else if (gendersearch == 'f')
            {
                 gendersearch = 'F';
            }

        for(int i = 0; i < list.getPersonsSize();++i)
        {
            if(gendersearch == list.getGender(i))
            {
                gendersearch = list.getGender(i);
                view(i);
            }
        }
        if(list.genderSearcher(gendersearch) == false)
        {
            cout << "Sorry that gender is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
            searching();
        }
    }
    else if (searchChoice == "3")
    {
            int yearsearch;
            cout << "Enter a year you want to search for: ";
            cin >> yearsearch;

            for(int i = 0; i < list.getPersonsSize();++i)
            {
                if(yearsearch == list.getBirth(i))
                {
                    yearsearch = list.getBirth(i);
                    view(i);
                }
            }
            if(list.yearSearcher(yearsearch) == false)
            {
                cout << "Sorry that year is not in our database, but you can add a new instance in the 'Add' section in the main menu." << endl;
                searching();
            }
    }
    else if (searchChoice == "4")
    {
        mainMenu();
    }
    else
    {
        cout << "Error reading input. Please enter a number between 1- 3." << endl;
        search();
    }
}
void ClassUI::remove()
{
    string name;
    cout << "Enter the full name of the person that you want to remove: ";
    cin.ignore();
    std::getline(std::cin,name);
    if (list.removePersonFound(name) == true)
    {
        char validateRemove;
        cout << "Person found!" << endl;
        cout << "Are you sure you want to remove this person? (y/n): ";
        cin >> validateRemove;

        if(validateRemove == 'y' || validateRemove == 'Y')
        {
            if(list.removePerson(name) == true)
            {
                cout << "Person removed!" << endl;
            }
            else
            {
                cout << "Person not removed!" << endl;
            }
        }

    }
    else
    {
        cout << "Person not found!" << endl;
    }
}
void ClassUI::save()
{
    list.saveFile();
}
void ClassUI::viewAll()
{
    for(int i = 0; i < list.getPersonsSize(); i++)
    {
        view(i);
    }
}
void ClassUI::yo()
{
    cout << endl;
    cout << "`8.`8888.      ,8'     ,o888888o.     " << endl;
    cout << " `8.`8888.    ,8'   . 8888     `88.   " << endl;
    cout << "  `8.`8888.  ,8'   ,8 8888       `8b  " << endl;
    cout << "   `8.`8888.,8'    88 8888        `8b " << endl;
    cout << "    `8.`88888'     88 8888         88 " << endl;
    cout << "     `8. 8888      88 8888         88 " << endl;
    cout << "      `8 8888      88 8888        ,8P " << endl;
    cout << "       8 8888      `8 8888       ,8P  " << endl;
    cout << "       8 8888       ` 8888     ,88'   " << endl;
    cout << "       8 8888          `8888888P'     " << endl;
    cout << endl;
}

string ClassUI::getQuotes()
{
    string quotes[5] = {"\"A good programmer is someone who always looks both ways before crossing a one-way street.\" (Doug Linder)",
                        "\"Programming is like sex. One mistake and you have to support it for the rest of your life.\" (Michael Sinz)",
                        "\"Walking on water and developing software from a specification are easy if both are frozen.\" (Edward V Berard)",
                        "\"One man's crappy software is another man's full time job.\" (Jessica Gaston)",
                        "\"A C program is like a fast dance on a newly waxed dance floor by people carrying razors.\" (Waldi Ravens)"
                       };
    int v1 = 0;
    srand (time(NULL));
    v1 = rand() % 5;
    return quotes[v1];
}
<|endoftext|>


<commit_before>// Copyright 2021 The IREE Authors
//
// Licensed 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

#include "iree/compiler/Dialect/Stream/Transforms/Passes.h"

#include <memory>

#include "iree/compiler/Dialect/Util/Transforms/Passes.h"
#include "mlir/Pass/PassOptions.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Transforms/Passes.h"

namespace mlir {
namespace iree_compiler {
namespace IREE {
namespace Stream {

//===----------------------------------------------------------------------===//
// Utilities
//===----------------------------------------------------------------------===//

static void addCleanupPatterns(OpPassManager &passManager) {
  // Standard MLIR cleanup.
  passManager.addPass(mlir::createCanonicalizerPass());
  passManager.addPass(mlir::createCSEPass());

  // Simplify util.global accesses; this can help with data flow tracking as
  // redundant store-loads are removed.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Util::createSimplifyGlobalAccessesPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Util::createSimplifyGlobalAccessesPass());

  // Cleanup and canonicalization of util.global (and other util ops).
  passManager.addPass(IREE::Util::createApplyPatternsPass());
  passManager.addPass(IREE::Util::createFoldGlobalsPass());
  passManager.addPass(IREE::Util::createFuseGlobalsPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-tensor-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamTensorPassPipeline(OpPassManager &passManager,
                                   const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Input cleanup and simplification
  //----------------------------------------------------------------------------

  // Verify we support the program.
  passManager.addPass(IREE::Stream::createVerifyInputPass());

  // Turn all constant ops into global variables and fix up the IR.
  // As many locations change and constants are deduplicated we'll end up with
  // a lot of extraneous IR (mostly global loads) and clean those up here.
  passManager.addPass(IREE::Stream::createOutlineConstantsPass());

  // Perform cleanup after constnat simplification as more canonicalizers may be
  // able to kick in.
  addCleanupPatterns(passManager);

  //----------------------------------------------------------------------------
  // Conversion
  //----------------------------------------------------------------------------

  // Converts from all input dialects into various levels of the stream dialect.
  // Tensor-like things go to stream.tensor.* ops while lower level buffer-like
  // things will go to stream.async.* ops.
  passManager.addPass(IREE::Stream::createConvertToStreamPass());

  // No more tensor.*/etc ops are allowed. This is conservative - there may be
  // a lot of ops we convert but this will catch the majority of stragglers.
  passManager.addPass(IREE::Stream::createVerifyLoweringToTensorsPass());

  //----------------------------------------------------------------------------
  // Constant/variable optimization
  //----------------------------------------------------------------------------

  // Cleanup globals that were created during conversion.
  addCleanupPatterns(passManager);

  // Bring all initializers together so that we can schedule them.
  passManager.addPass(IREE::Util::createCombineInitializersPass());

  //----------------------------------------------------------------------------
  // Stream affinity/assignment
  //----------------------------------------------------------------------------

  // TODO(benvanik): pin based on target backends here.
  // TODO(benvanik): compute affinities for executables.
  // TODO(benvanik): annotate all dispatches with preferred executable affinity.
  // TODO(benvanik): DFA to specify all value affinities and pin dispatches.
}

//===----------------------------------------------------------------------===//
// -iree-stream-async-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamAsyncPassPipeline(OpPassManager &passManager,
                                  const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Tensor lowering and resource management
  //----------------------------------------------------------------------------

  // Lower stream.tensor.* ops to stream.async.* ops based on
  // affinity/configuration assigned during placement.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createEncodeHostTensorsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createEncodeHostTensorsPass());
  passManager.addNestedPass<IREE::Stream::ExecutableOp>(
      IREE::Stream::createEncodeDeviceTensorsPass());

  // Expand builtins to dispatches. This may introduce new executables.
  passManager.addPass(IREE::Stream::createMaterializeBuiltinsPass());

  addCleanupPatterns(passManager);

  // Materialize copy-on-write behavior with explicit stream.async.* ops.
  // This will insert a lot of copies, so follow it up with a pass that elides
  // ones that aren't needed. This is easier to verify than if there was one
  // pass attempting to do both. Note that copy-on-write materialization is
  // required for correct execution while copy elision is for performance only
  // (though it's critical enough that it is not optional).
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createMaterializeCopyOnWritePass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createMaterializeCopyOnWritePass());
  passManager.addPass(IREE::Stream::createElideAsyncCopiesPass());

  // Refine lifetime of all resources across the module.
  // We do this after scheduling execution so that we know how the resources
  // move across devices. We do it before scheduling waves as lifetime doesn't
  // change and it makes the IR cleaner.
  passManager.addPass(IREE::Stream::createRefineUsagePass());

  //----------------------------------------------------------------------------
  // Stream formation and scheduling
  //----------------------------------------------------------------------------

  // Combine async work into execution regions.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleExecutionPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleExecutionPass());

  // Group concurrently executable work into waves.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleConcurrencyPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleConcurrencyPass());

  // Materialize timepoints across the entire module. This simplifies scheduling
  // of the timeline as we can shake the IR and see what timepoints we still
  // have left.
  passManager.addPass(IREE::Stream::createPropagateTimepointsPass());
  addCleanupPatterns(passManager);

  // TODO(benvanik): remove covered timepoints in awaits (dominance).

  // Everything must now be in stream.async.* form.
  passManager.addPass(IREE::Stream::createVerifyLoweringToAsyncPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-cmd-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamCmdPassPipeline(OpPassManager &passManager,
                                const TransformOptions &transformOptions) {
  // Schedule fine-grained allocations and insert placeholders for larger/longer
  // lifetime allocations.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleAllocationPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleAllocationPass());

  // TODO(benvanik): passes to convert alloc to alloca and thread through
  // streams. Ideally all transient allocs become stream-ordered allocas.
  // createPropagateTransientsPass()

  // Allocate backing storage for fused constant resources.
  // This expands packed constants into explicit forms with partitioned storage
  // buffers and upload logic.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createPackConstantsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createPackConstantsPass());

  // Pack fused allocations based on lifetime.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createPackAllocationsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createPackAllocationsPass());

  // Layout packed slices to emit the arithmetic required for all resource
  // offsets. This enables us to propagate the subviews across the program
  // below.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createLayoutSlicesPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createLayoutSlicesPass());

  // Propagate subviews throughout the program to unify resource storage access.
  // After propagation many resource SSA values can be deduped or folded by the
  // cleanup patterns.
  passManager.addPass(IREE::Stream::createPropagateSubviewsPass());
  addCleanupPatterns(passManager);

  // TODO(benvanik): outline streams (ala dispatch regions). Note that we may
  // want to do this earlier to enable better deduplication but that makes the
  // above passes trickier. Outlining may be more like "find chunks of streams
  // useful to move into secondary command buffers."

  // Everything must now be in explicit stream.cmd.* form.
  passManager.addPass(IREE::Stream::createVerifyLoweringToCmdPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-optimization-pipeline
//===----------------------------------------------------------------------===//

void buildStreamOptimizationPassPipeline(
    OpPassManager &passManager, const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Binding optimization
  //----------------------------------------------------------------------------

  if (transformOptions.optimizeBindings) {
    // Canonicalizer needs to run so that we have predictable inputs for fusion.
    passManager.addPass(mlir::createCanonicalizerPass());
    passManager.addPass(IREE::Stream::createFuseDispatchBindingsPass());

    // Folding operands requires that CSE folds the inputs that we check for.
    passManager.addPass(mlir::createCSEPass());
    passManager.addPass(IREE::Stream::createFoldUniformOperandsPass());

    // Only want to specialize after we've added all the operands we need above.
    // TODO(benvanik): make codegen more efficient with the specialized
    // constants. The lookup tables inserted are currently extremely slow on
    // some backends.
    // passManager.addPass(IREE::Stream::createSpecializeDispatchesPass());

    // TODO(benvanik): canonicalize bindings: we should sort the bindings by
    // the block argument order of the parent stream.cmd.execute. This will get
    // us more regular descriptor set layouts. We could also use some other
    // heuristics (all constant bindings -> transients -> external etc) to
    // make partitioning the bindings easier. Note we need to update both the
    // dispatches and the dispatch function argument order.
  }

  //----------------------------------------------------------------------------
  // Annotations to aid future lowering pipelines
  //----------------------------------------------------------------------------

  // Annotate dispatch region arguments based on the operands passed at dispatch
  // sites. This allows codegen to see the potential values for the operands
  // when operating locally on executables.
  passManager.addPass(IREE::Stream::createAnnotateDispatchArgumentsPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamTransformPassPipeline(
    OpPassManager &passManager, const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Primary pipeline stages (required)
  //----------------------------------------------------------------------------

  buildStreamTensorPassPipeline(passManager, transformOptions);
  buildStreamAsyncPassPipeline(passManager, transformOptions);
  buildStreamCmdPassPipeline(passManager, transformOptions);

  //----------------------------------------------------------------------------
  // Optimizations (may be required by some targets)
  //----------------------------------------------------------------------------

  buildStreamOptimizationPassPipeline(passManager, transformOptions);

  //----------------------------------------------------------------------------
  // Post-pipeline cleanup
  //----------------------------------------------------------------------------

  // Forming streams involves a fair amount of subgraph stitching, which can
  // cause duplication. Run CSE to collapse.
  addCleanupPatterns(passManager);

  // Symbol DCE any remaining variables/functions that are now no longer
  // required.
  passManager.addPass(mlir::createSymbolDCEPass());
}

//===----------------------------------------------------------------------===//
// Registration
//===----------------------------------------------------------------------===//

void registerStreamTransformPassPipelines() {
  PassPipelineRegistration<TransformOptions> tensorPassPipeline(
      "iree-stream-tensor-transformation-pipeline",
      "Lowers source dialects into stream.tensor.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamTensorPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> asyncPassPipeline(
      "iree-stream-async-transformation-pipeline",
      "Lowers stream.tensor.* to stream.async.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamAsyncPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> cmdPassPipeline(
      "iree-stream-cmd-transformation-pipeline",
      "Lowers stream.async.* to stream.cmd.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamCmdPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> optimizationPassPipeline(
      "iree-stream-optimization-pipeline",
      "Optimizes stream commands and resources (may be required for some "
      "targets).",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamOptimizationPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> transformPassPipeline(
      "iree-stream-transformation-pipeline",
      "Runs the full IREE stream dialect transformation pipeline.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamTransformPassPipeline(passManager, transformOptions);
      });
}

namespace {
#define GEN_PASS_REGISTRATION
#include "iree/compiler/Dialect/Stream/Transforms/Passes.h.inc"  // IWYU pragma: export
}  // namespace

void registerStreamPasses() {
  // Generated.
  registerPasses();

  // Pipelines.
  registerStreamTransformPassPipelines();
}

}  // namespace Stream
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Disabling the iree-stream-encode-device-tensors pass for now. There's some TBD work in codegen for type propagation/bufferization.<commit_after>// Copyright 2021 The IREE Authors
//
// Licensed 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

#include "iree/compiler/Dialect/Stream/Transforms/Passes.h"

#include <memory>

#include "iree/compiler/Dialect/Util/Transforms/Passes.h"
#include "mlir/Pass/PassOptions.h"
#include "mlir/Pass/PassRegistry.h"
#include "mlir/Transforms/Passes.h"

namespace mlir {
namespace iree_compiler {
namespace IREE {
namespace Stream {

//===----------------------------------------------------------------------===//
// Utilities
//===----------------------------------------------------------------------===//

static void addCleanupPatterns(OpPassManager &passManager) {
  // Standard MLIR cleanup.
  passManager.addPass(mlir::createCanonicalizerPass());
  passManager.addPass(mlir::createCSEPass());

  // Simplify util.global accesses; this can help with data flow tracking as
  // redundant store-loads are removed.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Util::createSimplifyGlobalAccessesPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Util::createSimplifyGlobalAccessesPass());

  // Cleanup and canonicalization of util.global (and other util ops).
  passManager.addPass(IREE::Util::createApplyPatternsPass());
  passManager.addPass(IREE::Util::createFoldGlobalsPass());
  passManager.addPass(IREE::Util::createFuseGlobalsPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-tensor-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamTensorPassPipeline(OpPassManager &passManager,
                                   const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Input cleanup and simplification
  //----------------------------------------------------------------------------

  // Verify we support the program.
  passManager.addPass(IREE::Stream::createVerifyInputPass());

  // Turn all constant ops into global variables and fix up the IR.
  // As many locations change and constants are deduplicated we'll end up with
  // a lot of extraneous IR (mostly global loads) and clean those up here.
  passManager.addPass(IREE::Stream::createOutlineConstantsPass());

  // Perform cleanup after constnat simplification as more canonicalizers may be
  // able to kick in.
  addCleanupPatterns(passManager);

  //----------------------------------------------------------------------------
  // Conversion
  //----------------------------------------------------------------------------

  // Converts from all input dialects into various levels of the stream dialect.
  // Tensor-like things go to stream.tensor.* ops while lower level buffer-like
  // things will go to stream.async.* ops.
  passManager.addPass(IREE::Stream::createConvertToStreamPass());

  // No more tensor.*/etc ops are allowed. This is conservative - there may be
  // a lot of ops we convert but this will catch the majority of stragglers.
  passManager.addPass(IREE::Stream::createVerifyLoweringToTensorsPass());

  //----------------------------------------------------------------------------
  // Constant/variable optimization
  //----------------------------------------------------------------------------

  // Cleanup globals that were created during conversion.
  addCleanupPatterns(passManager);

  // Bring all initializers together so that we can schedule them.
  passManager.addPass(IREE::Util::createCombineInitializersPass());

  //----------------------------------------------------------------------------
  // Stream affinity/assignment
  //----------------------------------------------------------------------------

  // TODO(benvanik): pin based on target backends here.
  // TODO(benvanik): compute affinities for executables.
  // TODO(benvanik): annotate all dispatches with preferred executable affinity.
  // TODO(benvanik): DFA to specify all value affinities and pin dispatches.
}

//===----------------------------------------------------------------------===//
// -iree-stream-async-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamAsyncPassPipeline(OpPassManager &passManager,
                                  const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Tensor lowering and resource management
  //----------------------------------------------------------------------------

  // Lower stream.tensor.* ops to stream.async.* ops based on
  // affinity/configuration assigned during placement.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createEncodeHostTensorsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createEncodeHostTensorsPass());
  // TODO(ravishankarm): enable when codegen can handle extui/trunc ops.
  // passManager.addNestedPass<IREE::Stream::ExecutableOp>(
  //     IREE::Stream::createEncodeDeviceTensorsPass());

  // Expand builtins to dispatches. This may introduce new executables.
  passManager.addPass(IREE::Stream::createMaterializeBuiltinsPass());

  addCleanupPatterns(passManager);

  // Materialize copy-on-write behavior with explicit stream.async.* ops.
  // This will insert a lot of copies, so follow it up with a pass that elides
  // ones that aren't needed. This is easier to verify than if there was one
  // pass attempting to do both. Note that copy-on-write materialization is
  // required for correct execution while copy elision is for performance only
  // (though it's critical enough that it is not optional).
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createMaterializeCopyOnWritePass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createMaterializeCopyOnWritePass());
  passManager.addPass(IREE::Stream::createElideAsyncCopiesPass());

  // Refine lifetime of all resources across the module.
  // We do this after scheduling execution so that we know how the resources
  // move across devices. We do it before scheduling waves as lifetime doesn't
  // change and it makes the IR cleaner.
  passManager.addPass(IREE::Stream::createRefineUsagePass());

  //----------------------------------------------------------------------------
  // Stream formation and scheduling
  //----------------------------------------------------------------------------

  // Combine async work into execution regions.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleExecutionPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleExecutionPass());

  // Group concurrently executable work into waves.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleConcurrencyPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleConcurrencyPass());

  // Materialize timepoints across the entire module. This simplifies scheduling
  // of the timeline as we can shake the IR and see what timepoints we still
  // have left.
  passManager.addPass(IREE::Stream::createPropagateTimepointsPass());
  addCleanupPatterns(passManager);

  // TODO(benvanik): remove covered timepoints in awaits (dominance).

  // Everything must now be in stream.async.* form.
  passManager.addPass(IREE::Stream::createVerifyLoweringToAsyncPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-cmd-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamCmdPassPipeline(OpPassManager &passManager,
                                const TransformOptions &transformOptions) {
  // Schedule fine-grained allocations and insert placeholders for larger/longer
  // lifetime allocations.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createScheduleAllocationPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createScheduleAllocationPass());

  // TODO(benvanik): passes to convert alloc to alloca and thread through
  // streams. Ideally all transient allocs become stream-ordered allocas.
  // createPropagateTransientsPass()

  // Allocate backing storage for fused constant resources.
  // This expands packed constants into explicit forms with partitioned storage
  // buffers and upload logic.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createPackConstantsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createPackConstantsPass());

  // Pack fused allocations based on lifetime.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createPackAllocationsPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createPackAllocationsPass());

  // Layout packed slices to emit the arithmetic required for all resource
  // offsets. This enables us to propagate the subviews across the program
  // below.
  passManager.addNestedPass<IREE::Util::InitializerOp>(
      IREE::Stream::createLayoutSlicesPass());
  passManager.addNestedPass<mlir::FuncOp>(
      IREE::Stream::createLayoutSlicesPass());

  // Propagate subviews throughout the program to unify resource storage access.
  // After propagation many resource SSA values can be deduped or folded by the
  // cleanup patterns.
  passManager.addPass(IREE::Stream::createPropagateSubviewsPass());
  addCleanupPatterns(passManager);

  // TODO(benvanik): outline streams (ala dispatch regions). Note that we may
  // want to do this earlier to enable better deduplication but that makes the
  // above passes trickier. Outlining may be more like "find chunks of streams
  // useful to move into secondary command buffers."

  // Everything must now be in explicit stream.cmd.* form.
  passManager.addPass(IREE::Stream::createVerifyLoweringToCmdPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-optimization-pipeline
//===----------------------------------------------------------------------===//

void buildStreamOptimizationPassPipeline(
    OpPassManager &passManager, const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Binding optimization
  //----------------------------------------------------------------------------

  if (transformOptions.optimizeBindings) {
    // Canonicalizer needs to run so that we have predictable inputs for fusion.
    passManager.addPass(mlir::createCanonicalizerPass());
    passManager.addPass(IREE::Stream::createFuseDispatchBindingsPass());

    // Folding operands requires that CSE folds the inputs that we check for.
    passManager.addPass(mlir::createCSEPass());
    passManager.addPass(IREE::Stream::createFoldUniformOperandsPass());

    // Only want to specialize after we've added all the operands we need above.
    // TODO(benvanik): make codegen more efficient with the specialized
    // constants. The lookup tables inserted are currently extremely slow on
    // some backends.
    // passManager.addPass(IREE::Stream::createSpecializeDispatchesPass());

    // TODO(benvanik): canonicalize bindings: we should sort the bindings by
    // the block argument order of the parent stream.cmd.execute. This will get
    // us more regular descriptor set layouts. We could also use some other
    // heuristics (all constant bindings -> transients -> external etc) to
    // make partitioning the bindings easier. Note we need to update both the
    // dispatches and the dispatch function argument order.
  }

  //----------------------------------------------------------------------------
  // Annotations to aid future lowering pipelines
  //----------------------------------------------------------------------------

  // Annotate dispatch region arguments based on the operands passed at dispatch
  // sites. This allows codegen to see the potential values for the operands
  // when operating locally on executables.
  passManager.addPass(IREE::Stream::createAnnotateDispatchArgumentsPass());
}

//===----------------------------------------------------------------------===//
// -iree-stream-transformation-pipeline
//===----------------------------------------------------------------------===//

void buildStreamTransformPassPipeline(
    OpPassManager &passManager, const TransformOptions &transformOptions) {
  //----------------------------------------------------------------------------
  // Primary pipeline stages (required)
  //----------------------------------------------------------------------------

  buildStreamTensorPassPipeline(passManager, transformOptions);
  buildStreamAsyncPassPipeline(passManager, transformOptions);
  buildStreamCmdPassPipeline(passManager, transformOptions);

  //----------------------------------------------------------------------------
  // Optimizations (may be required by some targets)
  //----------------------------------------------------------------------------

  buildStreamOptimizationPassPipeline(passManager, transformOptions);

  //----------------------------------------------------------------------------
  // Post-pipeline cleanup
  //----------------------------------------------------------------------------

  // Forming streams involves a fair amount of subgraph stitching, which can
  // cause duplication. Run CSE to collapse.
  addCleanupPatterns(passManager);

  // Symbol DCE any remaining variables/functions that are now no longer
  // required.
  passManager.addPass(mlir::createSymbolDCEPass());
}

//===----------------------------------------------------------------------===//
// Registration
//===----------------------------------------------------------------------===//

void registerStreamTransformPassPipelines() {
  PassPipelineRegistration<TransformOptions> tensorPassPipeline(
      "iree-stream-tensor-transformation-pipeline",
      "Lowers source dialects into stream.tensor.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamTensorPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> asyncPassPipeline(
      "iree-stream-async-transformation-pipeline",
      "Lowers stream.tensor.* to stream.async.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamAsyncPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> cmdPassPipeline(
      "iree-stream-cmd-transformation-pipeline",
      "Lowers stream.async.* to stream.cmd.* IR.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamCmdPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> optimizationPassPipeline(
      "iree-stream-optimization-pipeline",
      "Optimizes stream commands and resources (may be required for some "
      "targets).",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamOptimizationPassPipeline(passManager, transformOptions);
      });
  PassPipelineRegistration<TransformOptions> transformPassPipeline(
      "iree-stream-transformation-pipeline",
      "Runs the full IREE stream dialect transformation pipeline.",
      [](OpPassManager &passManager, const TransformOptions &transformOptions) {
        buildStreamTransformPassPipeline(passManager, transformOptions);
      });
}

namespace {
#define GEN_PASS_REGISTRATION
#include "iree/compiler/Dialect/Stream/Transforms/Passes.h.inc"  // IWYU pragma: export
}  // namespace

void registerStreamPasses() {
  // Generated.
  registerPasses();

  // Pipelines.
  registerStreamTransformPassPipelines();
}

}  // namespace Stream
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir
<|endoftext|>