<commit_before>#include <QPrintDialog>
#include <QPainter>
#include <QDebug>
#include <QPrintPreviewWidget>
#include <QPrintPreviewDialog>
#include "converters/convertertopdf.hpp"
#include "converters/convertertohtml.hpp"
#include "replacer.hpp"
#include "engine.hpp"

namespace qtreports
{

    Engine::Engine( QObject * parent ) :
        QObject( parent ),
        m_isOpened( false )
    {}

    Engine::Engine( const QString & path, QObject * parent ) :
        Engine( parent )
    {
        open( path );
    }

    Engine::~Engine() {}

    bool	Engine::open( const QString & path )
    {
        if( isOpened() )
        {
            close();
        }

        detail::Parser parser;
        if( !parser.parse( path ) )
        {
            m_lastError = "Parsing error: " + parser.getLastError();
            return false;
        }

        m_isOpened = true;
        m_compiledPath = path;
        m_report = parser.getReport();

        fillColumnsFromReport(); //MB as ProcessedDB::createColumns( ReportPtr )

        return true;
    }

    void    Engine::close()
    {
        m_isOpened = false;
        m_compiledPath.clear();
        m_report.clear();
    }

    bool	Engine::setParameters( const QMap< QString, QVariant > & parameters )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        m_report->setParameters( parameters );

        return true;
    }

    bool	Engine::setConnection( const QSqlDatabase & connection )
    {
        if( !connection.isOpen() )
        {
            m_lastError = "Connection not open";
            return false;
        }

        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        m_dbConnection = connection;

        if( !prepareDB() )
        {
            m_lastError = "Error in prepare db process: " + m_lastError;
            return false;
        }

        m_report->setRowCount( m_processedDB.getMaxRowCount() );

        for( auto && field : m_report->getFields() )
        {
            auto name = field->getName();
            auto value = m_processedDB.getColumn( name );
            m_report->setFieldData( name, value );
        }

        m_processedDB.setParameters( m_report->getParameters() );

        return true;
    }

    bool    Engine::setDataSource( const QMap< QString, QVector< QVariant > > & source )
    {
        //Need check parameters
        //m_dataSource = columnsSet;

        if( !prepareDataSource( source ) )
        {
            m_lastError = "Error in prepare data source: " + m_lastError;
            return false;
        }

        m_report->setRowCount( m_processedDB.getMaxRowCount() );

        for( auto && field : m_report->getFields() )
        {
            auto name = field->getName();
            auto value = m_processedDB.getColumn( name );
            m_report->setFieldData( name, value );
        }

        return true;
    }

    bool    Engine::setQuery( const QString & query )
    {
        //Need check parameters
        auto queries = query.split( ";", QString::SkipEmptyParts );
        executeQueries( queries );

        m_lastError = query;
        return true;
    }

    bool    Engine::addScript( const QString & script )
    {
        //Need check parameters
        m_scripts.append( script );

        return true;
    }

    bool    Engine::setDataModel( const QAbstractItemModel & model )
    {
        //Need check parameters
        Q_UNUSED( model )
        return true;
    }

    bool	Engine::createPDF( const QString & path )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        detail::ConverterToPDF converter( m_report );
        auto result = converter.convert( path );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return false;
        }

        return true;
    }

    bool	Engine::createHTML( const QString & path )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        detail::ConverterToHTML converter( m_report );
        auto result = converter.convert( path );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return false;
        }

        return true;
    }

    QWidgetPtr	Engine::createWidget()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return QWidgetPtr();
        }

        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return QWidgetPtr();
        }

        return converter.getQWidget();
    }

    QWidgetPtr	Engine::createLayout()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return QWidgetPtr();
        }

        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Layout );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return QWidgetPtr();
        }

        return converter.getQWidget();
    }

    bool	Engine::print()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        QPrinter printer;
        QPrintPreviewDialog preview( &printer );
        connect(
            &preview, &QPrintPreviewDialog::paintRequested,
            this, &Engine::drawPreview
            );
        preview.exec();

        return true;
    }

    void	Engine::drawPreview( QPrinter * printer )
    {
        auto temp = m_report->getOrientation();
        m_report->setOrientation( printer->orientation() );
        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report );
        m_report->setOrientation( temp );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return;
        }

        auto widgets = converter.getPages();
        if( widgets.isEmpty() )
        {
            m_lastError = "Cannot print widget: all pages is empty";
            return;
        }

        auto widget = widgets.value( 0 );

        QRectF rect = printer->pageRect();
        QPainter painter( printer );
        qreal scale = rect.width() / widget->width();

        widget->resize( widget->width(), rect.height() / scale );
        painter.scale( scale, scale );

        for( int i = 0; i < widgets.size(); ++i )
        {
            i != 0 ? printer->newPage() : 0;
            widget = widgets.value( i );
            if( widget.isNull() )
            {
                m_lastError = "Error in print process: printed widget is empty";
                return;
            }

            //Magic
            widget->show();
            widget->hide();
            widget->render( &painter );
        }
    }

    bool    Engine::prepareDB() {
        return setQuery( m_report->getQuery() );
    }

    bool    Engine::prepareDataSource( const QMap< QString, QVector< QVariant > > & source )
    {
        QMapIterator< QString, QVector< QVariant > > iterator( source );
        while( iterator.hasNext() )
        {
            iterator.next();
            auto field = m_report->getField( iterator.key() );
            if( field.isNull() )
            {
                m_lastError = "Report not have column: " + iterator.key();
                return false;
            }

            field->setData( iterator.value() );
        }

        return true;
    }

    void    Engine::fillColumnsFromReport()
    {
        for( auto && field : m_report->getFields() )
        {
            m_processedDB.addEmptyColumn( field->getName() );
        }
    }

    void    Engine::executeQueries( const QStringList & queries )
    {
        for( auto && query : queries )
        {
            auto model = new QSqlQueryModel();
            model->setQuery( query, m_dbConnection );
            for( int row = 0; row < model->rowCount(); row++ )
            {
                QSqlRecord rec = model->record( row );
                for( int col = 0; col < rec.count(); col++ )
                {
                    m_processedDB.appendColumnData( rec.fieldName( col ), rec.field( col ).value() );
                }
            }
        }
    }

    bool    Engine::isOpened() const
    {
        return m_isOpened;
    }

    detail::ReportPtr	Engine::getReport() const
    {
        return m_report;
    }

    const QString   Engine::getLastError() const
    {
        return m_lastError;
    }

}
<commit_msg>Fix memory leak.<commit_after>#include <QPrintDialog>
#include <QPainter>
#include <QDebug>
#include <QPrintPreviewWidget>
#include <QPrintPreviewDialog>
#include "converters/convertertopdf.hpp"
#include "converters/convertertohtml.hpp"
#include "replacer.hpp"
#include "engine.hpp"

namespace qtreports
{

    Engine::Engine( QObject * parent ) :
        QObject( parent ),
        m_isOpened( false )
    {}

    Engine::Engine( const QString & path, QObject * parent ) :
        Engine( parent )
    {
        open( path );
    }

    Engine::~Engine() {}

    bool	Engine::open( const QString & path )
    {
        if( isOpened() )
        {
            close();
        }

        detail::Parser parser;
        if( !parser.parse( path ) )
        {
            m_lastError = "Parsing error: " + parser.getLastError();
            return false;
        }

        m_isOpened = true;
        m_compiledPath = path;
        m_report = parser.getReport();

        fillColumnsFromReport(); //MB as ProcessedDB::createColumns( ReportPtr )

        return true;
    }

    void    Engine::close()
    {
        m_isOpened = false;
        m_compiledPath.clear();
        m_report.clear();
    }

    bool	Engine::setParameters( const QMap< QString, QVariant > & parameters )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        m_report->setParameters( parameters );

        return true;
    }

    bool	Engine::setConnection( const QSqlDatabase & connection )
    {
        if( !connection.isOpen() )
        {
            m_lastError = "Connection not open";
            return false;
        }

        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        m_dbConnection = connection;

        if( !prepareDB() )
        {
            m_lastError = "Error in prepare db process: " + m_lastError;
            return false;
        }

        m_report->setRowCount( m_processedDB.getMaxRowCount() );

        for( auto && field : m_report->getFields() )
        {
            auto name = field->getName();
            auto value = m_processedDB.getColumn( name );
            m_report->setFieldData( name, value );
        }

        m_processedDB.setParameters( m_report->getParameters() );

        return true;
    }

    bool    Engine::setDataSource( const QMap< QString, QVector< QVariant > > & source )
    {
        //Need check parameters
        //m_dataSource = columnsSet;

        if( !prepareDataSource( source ) )
        {
            m_lastError = "Error in prepare data source: " + m_lastError;
            return false;
        }

        m_report->setRowCount( m_processedDB.getMaxRowCount() );

        for( auto && field : m_report->getFields() )
        {
            auto name = field->getName();
            auto value = m_processedDB.getColumn( name );
            m_report->setFieldData( name, value );
        }

        return true;
    }

    bool    Engine::setQuery( const QString & query )
    {
        //Need check parameters
        auto queries = query.split( ";", QString::SkipEmptyParts );
        executeQueries( queries );

        m_lastError = query;
        return true;
    }

    bool    Engine::addScript( const QString & script )
    {
        //Need check parameters
        m_scripts.append( script );

        return true;
    }

    bool    Engine::setDataModel( const QAbstractItemModel & model )
    {
        //Need check parameters
        Q_UNUSED( model );
        return true;
    }

    bool	Engine::createPDF( const QString & path )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        detail::ConverterToPDF converter( m_report );
        auto result = converter.convert( path );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return false;
        }

        return true;
    }

    bool	Engine::createHTML( const QString & path )
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        detail::ConverterToHTML converter( m_report );
        auto result = converter.convert( path );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return false;
        }

        return true;
    }

    QWidgetPtr	Engine::createWidget()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return QWidgetPtr();
        }

        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return QWidgetPtr();
        }

        return converter.getQWidget();
    }

    QWidgetPtr	Engine::createLayout()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return QWidgetPtr();
        }

        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Layout );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return QWidgetPtr();
        }

        return converter.getQWidget();
    }

    bool	Engine::print()
    {
        if( m_report.isNull() )
        {
            m_lastError = "Report is empty. Please open report file";
            return false;
        }

        QPrinter printer;
        QPrintPreviewDialog preview( &printer );
        connect(
            &preview, &QPrintPreviewDialog::paintRequested,
            this, &Engine::drawPreview
        );
        preview.exec();

        return true;
    }

    void	Engine::drawPreview( QPrinter * printer )
    {
        auto temp = m_report->getOrientation();
        m_report->setOrientation( printer->orientation() );
        detail::ConverterToQWidget converter( m_report );
        auto result = converter.convert( detail::ConverterToQWidget::WidgetType::Report );
        m_report->setOrientation( temp );
        if( !result )
        {
            m_lastError = converter.getLastError();
            return;
        }

        auto widgets = converter.getPages();
        if( widgets.isEmpty() )
        {
            m_lastError = "Cannot print widget: all pages is empty";
            return;
        }

        auto widget = widgets.value( 0 );

        QRectF rect = printer->pageRect();
        QPainter painter( printer );
        qreal scale = rect.width() / widget->width();

        widget->resize( widget->width(), rect.height() / scale );
        painter.scale( scale, scale );

        for( int i = 0; i < widgets.size(); ++i )
        {
            i != 0 ? printer->newPage() : 0;
            widget = widgets.value( i );
            if( widget.isNull() )
            {
                m_lastError = "Error in print process: printed widget is empty";
                return;
            }

            //Magic
            widget->show();
            widget->hide();
            widget->render( &painter );
        }
    }

    bool    Engine::prepareDB()
    {
        return setQuery( m_report->getQuery() );
    }

    bool    Engine::prepareDataSource( const QMap< QString, QVector< QVariant > > & source )
    {
        QMapIterator< QString, QVector< QVariant > > iterator( source );
        while( iterator.hasNext() )
        {
            iterator.next();
            auto field = m_report->getField( iterator.key() );
            if( field.isNull() )
            {
                m_lastError = "Report not have column: " + iterator.key();
                return false;
            }

            field->setData( iterator.value() );
        }

        return true;
    }

    void    Engine::fillColumnsFromReport()
    {
        for( auto && field : m_report->getFields() )
        {
            m_processedDB.addEmptyColumn( field->getName() );
        }
    }

    void    Engine::executeQueries( const QStringList & queries )
    {
        QSqlQueryModel model;
        for( auto && query : queries )
        {
            model.setQuery( query, m_dbConnection );
            for( int row = 0; row < model.rowCount(); row++ )
            {
                QSqlRecord rec = model.record( row );
                for( int col = 0; col < rec.count(); col++ )
                {
                    auto columnName = rec.fieldName( col );
                    auto fieldValue = rec.field( col ).value();
                    m_processedDB.appendColumnData( columnName, fieldValue );
                }
            }
        }
    }

    bool    Engine::isOpened() const
    {
        return m_isOpened;
    }

    detail::ReportPtr	Engine::getReport() const
    {
        return m_report;
    }

    const QString   Engine::getLastError() const
    {
        return m_lastError;
    }

}
<|endoftext|>


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

#include "swift/SILAnalysis/RCIdentityAnalysis.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SIL/SILInstruction.h"
#include "llvm/Support/CommandLine.h"

using namespace swift;

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

/// Returns true if V is an enum without a payload.
///
/// We perform this computation by checking if V is an enum instruction without
/// an argument. I am using a helper here in case I find more cases where I need
/// to expand it.
static bool isNoPayloadEnum(SILValue V) {
  auto *EI = dyn_cast<EnumInst>(V);
  if (!EI)
    return false;

  return !EI->hasOperand();
}

static bool isRCIdentityPreservingCast(ValueKind Kind) {
  switch (Kind) {
  case ValueKind::UpcastInst:
  case ValueKind::UncheckedRefCastInst:
  case ValueKind::UncheckedAddrCastInst:
  case ValueKind::UnconditionalCheckedCastInst:
  case ValueKind::UncheckedRefBitCastInst:
  case ValueKind::InitExistentialRefInst:
  case ValueKind::OpenExistentialRefInst:
  case ValueKind::RefToBridgeObjectInst:
  case ValueKind::BridgeObjectToRefInst:
    return true;
  default:
    return false;
  }
}

//===----------------------------------------------------------------------===//
//                                  Analysis
//===----------------------------------------------------------------------===//

/// Returns true if FirstIV is a SILArgument or SILInstruction in a BB that
/// dominates the BB of A.
static bool dominatesArgument(DominanceInfo *DI, SILArgument *A,
                              SILValue FirstIV) {
  SILBasicBlock *OtherBB = FirstIV->getParentBB();
  if (!OtherBB || OtherBB == A->getParent())
    return false;
  return DI->dominates(OtherBB, A->getParent());
}

static SILValue stripRCIdentityPreservingInsts(SILValue V) {
  // First strip off RC identity preserving casts.
  if (isRCIdentityPreservingCast(V->getKind()))
    return cast<SILInstruction>(V.getDef())->getOperand(0);

  // Then if we have a struct_extract that is extracting a non-trivial member
  // from a struct with no other non-trivial members, a ref count operation on
  // the struct is equivalent to a ref count operation on the extracted
  // member. Strip off the extract.
  if (auto *SEI = dyn_cast<StructExtractInst>(V))
    if (SEI->isFieldOnlyNonTrivialField())
      return SEI->getOperand();

  // If we have a struct instruction with only one non-trivial stored field, the
  // only reference count that can be modified is the non-trivial field. Return
  // the non-trivial field.
  if (auto *SI = dyn_cast<StructInst>(V))
    if (SILValue NewValue = SI->getUniqueNonTrivialFieldValue())
      return NewValue;

  // If we have an unchecked_enum_data, strip off the unchecked_enum_data.
  if (auto *UEDI = dyn_cast<UncheckedEnumDataInst>(V))
    return UEDI->getOperand();

  // If we have an enum instruction with a payload, strip off the enum to
  // expose the enum's payload.
  if (auto *EI = dyn_cast<EnumInst>(V))
    if (EI->hasOperand())
      return EI->getOperand();

  // If we have a tuple_extract that is extracting the only non trivial member
  // of a tuple, a retain_value on the tuple is equivalent to a retain_value on
  // the extracted value.
  if (auto *TEI = dyn_cast<TupleExtractInst>(V))
    if (TEI->isEltOnlyNonTrivialElt())
      return TEI->getOperand();

  // If we are forming a tuple and the tuple only has one element with reference
  // semantics, a retain_value on the tuple is equivalent to a retain value on
  // the tuple operand.
  if (auto *TI = dyn_cast<TupleInst>(V))
    if (SILValue NewValue = TI->getUniqueNonTrivialElt())
      return NewValue;

  return SILValue();
}

/// Return the underlying SILValue after stripping off SILArguments that can not
/// affect RC identity if our BB has only one predecessor.
SILValue
RCIdentityAnalysis::
stripRCIdentityPreservingArgs(SILValue V, unsigned RecursionDepth) {
  auto *A = dyn_cast<SILArgument>(V);
  if (!A) {
    return SILValue();
  }

  // If we already visited this BB, don't reprocess it since we have a cycle.
  if (!VisitedArgs.insert(A).second) {
    return SILValue();
  }

  // Ok, this is the first time that we have visited this BB. Get the
  // SILArgument's incoming values. If we don't have an incoming value for each
  // one of our predecessors, just return SILValue().
  llvm::SmallVector<SILValue, 8> IncomingValues;
  if (!A->getIncomingValues(IncomingValues) || IncomingValues.empty()) {
    return SILValue();
  }

  unsigned IVListSize = IncomingValues.size();

  // If we only have one incoming value, just return the identity root of that
  // incoming value. There can be no loop problems.
  if (IVListSize == 1) {
    return getRCIdentityRootInner(IncomingValues[0], RecursionDepth+1);
  }

  // Ok, we have multiple predecessors. First find the first non-payloaded enum.
  unsigned i = 0;
  for (; i < IVListSize && isNoPayloadEnum(IncomingValues[i]); ++i) {}

  // If we did not find any non-payloaded enum, there is no RC associated with
  // this Phi node. Just return SILValue().
  if (i == IVListSize)
    return SILValue();

  SILValue FirstIV = IncomingValues[i];

  // Strip off any non-argument instructions from IV. We know that
  while (SILValue NewIV = stripRCIdentityPreservingInsts(FirstIV))
    FirstIV = NewIV;

  // Then make sure that this incoming value is from a BB which is different
  // from our BB and dominates our BB. Otherwise, just return SILValue() there
  // is nothing we can do hter.
  DominanceInfo *DI = DA->getDomInfo(A->getFunction());
  if (!dominatesArgument(DI, A, FirstIV))
    return SILValue();

  // Ok, it is safe to continue stripping from this argument. Perform the
  // recursive stripping.
  FirstIV = getRCIdentityRootInner(FirstIV, RecursionDepth+1);
  while (i < IVListSize) {
    SILValue IV = IncomingValues[i++];

    // If IV is a no payload enum, we don't care about it. Skip it.
    if (isNoPayloadEnum(IV))
      continue;

    // Strip off any non-argument instructions from IV. We know that
    while (SILValue NewIV = stripRCIdentityPreservingInsts(IV))
      IV = NewIV;

    // Then make sure that this incoming value is from a BB which is different
    // from our BB and dominates our BB. Otherwise, just return SILValue() there
    // is nothing we can do hter.
    if (!dominatesArgument(DI, A, IV))
      return SILValue();

    // Ok, it is safe to continue stripping incoming values. Perform the
    // stripping and check if the stripped value equals FirstIV. If it is not
    // so, then bail. We found a conflicting value in our merging.
    if (getRCIdentityRootInner(IV, RecursionDepth+1) != FirstIV)
      return SILValue();
  }

  // Ok all our values match! Return FirstIV.
  return FirstIV;
}

SILValue
RCIdentityAnalysis::
stripRCIdentityPreservingOps(SILValue V, unsigned RecursionDepth) {
  while (true) {
    // First strip off any RC identity preserving instructions. This is cheap.
    if (SILValue NewV = stripRCIdentityPreservingInsts(V)) {
      V = NewV;
      continue;
    }

    // Once we have done all of the easy work, try to see if we can strip off
    // any RCIdentityPreserving args. This is potentially expensive since we
    // need to perform additional stripping on the argument provided to this
    // argument from each predecessor BB. There is a counter in
    // getRCIdentityRootInner that ensures we don't do too many.
    SILValue NewV = stripRCIdentityPreservingArgs(V, RecursionDepth);
    if (!NewV)
      break;

    V = NewV;
  }

  return V;
}

//===----------------------------------------------------------------------===//
//                              Main Entry Point
//===----------------------------------------------------------------------===//

SILValue RCIdentityAnalysis::getRCIdentityRootInner(SILValue V,
                                                    unsigned RecursionDepth) {
  // Only allow this method to be recursed on for a limited number of times to
  // make sure we don't explode compile time.
  if (RecursionDepth >= MaxRecursionDepth)
    return SILValue();

  // First check the cache.
  auto Pair = Cache.find(V);
  if (Pair != Cache.end())
    return Pair->second;

  SILValue NewValue = stripRCIdentityPreservingOps(V, RecursionDepth);
  if (!NewValue)
    return SILValue();

  // We can get back V if our analysis completely fails. There is no point in
  // storing this value into the cache so just return it.
  if (NewValue == V)
    return V;

  return Cache[V] = NewValue;
}

SILValue RCIdentityAnalysis::getRCIdentityRoot(SILValue V) {
  SILValue Root = getRCIdentityRootInner(V, 0);
  VisitedArgs.clear();

  // If we fail to find a root, return V.
  if (!Root)
    return V;

  return Root;
}

SILAnalysis *swift::createRCIdentityAnalysis(SILModule *M, SILPassManager *PM) {
  return new RCIdentityAnalysis(M, PM);
}
<commit_msg>[rc-id] Add an option that stops RCIdentityAnalysis from stripping off arguments.<commit_after>//===--- RCIdentityAnalysis.cpp -------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/SILAnalysis/RCIdentityAnalysis.h"
#include "swift/SILAnalysis/DominanceAnalysis.h"
#include "swift/SIL/SILInstruction.h"
#include "llvm/Support/CommandLine.h"

using namespace swift;

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

/// Returns true if V is an enum without a payload.
///
/// We perform this computation by checking if V is an enum instruction without
/// an argument. I am using a helper here in case I find more cases where I need
/// to expand it.
static bool isNoPayloadEnum(SILValue V) {
  auto *EI = dyn_cast<EnumInst>(V);
  if (!EI)
    return false;

  return !EI->hasOperand();
}

static bool isRCIdentityPreservingCast(ValueKind Kind) {
  switch (Kind) {
  case ValueKind::UpcastInst:
  case ValueKind::UncheckedRefCastInst:
  case ValueKind::UncheckedAddrCastInst:
  case ValueKind::UnconditionalCheckedCastInst:
  case ValueKind::UncheckedRefBitCastInst:
  case ValueKind::InitExistentialRefInst:
  case ValueKind::OpenExistentialRefInst:
  case ValueKind::RefToBridgeObjectInst:
  case ValueKind::BridgeObjectToRefInst:
    return true;
  default:
    return false;
  }
}

//===----------------------------------------------------------------------===//
//                                  Analysis
//===----------------------------------------------------------------------===//

/// Returns true if FirstIV is a SILArgument or SILInstruction in a BB that
/// dominates the BB of A.
static bool dominatesArgument(DominanceInfo *DI, SILArgument *A,
                              SILValue FirstIV) {
  SILBasicBlock *OtherBB = FirstIV->getParentBB();
  if (!OtherBB || OtherBB == A->getParent())
    return false;
  return DI->dominates(OtherBB, A->getParent());
}

static SILValue stripRCIdentityPreservingInsts(SILValue V) {
  // First strip off RC identity preserving casts.
  if (isRCIdentityPreservingCast(V->getKind()))
    return cast<SILInstruction>(V.getDef())->getOperand(0);

  // Then if we have a struct_extract that is extracting a non-trivial member
  // from a struct with no other non-trivial members, a ref count operation on
  // the struct is equivalent to a ref count operation on the extracted
  // member. Strip off the extract.
  if (auto *SEI = dyn_cast<StructExtractInst>(V))
    if (SEI->isFieldOnlyNonTrivialField())
      return SEI->getOperand();

  // If we have a struct instruction with only one non-trivial stored field, the
  // only reference count that can be modified is the non-trivial field. Return
  // the non-trivial field.
  if (auto *SI = dyn_cast<StructInst>(V))
    if (SILValue NewValue = SI->getUniqueNonTrivialFieldValue())
      return NewValue;

  // If we have an unchecked_enum_data, strip off the unchecked_enum_data.
  if (auto *UEDI = dyn_cast<UncheckedEnumDataInst>(V))
    return UEDI->getOperand();

  // If we have an enum instruction with a payload, strip off the enum to
  // expose the enum's payload.
  if (auto *EI = dyn_cast<EnumInst>(V))
    if (EI->hasOperand())
      return EI->getOperand();

  // If we have a tuple_extract that is extracting the only non trivial member
  // of a tuple, a retain_value on the tuple is equivalent to a retain_value on
  // the extracted value.
  if (auto *TEI = dyn_cast<TupleExtractInst>(V))
    if (TEI->isEltOnlyNonTrivialElt())
      return TEI->getOperand();

  // If we are forming a tuple and the tuple only has one element with reference
  // semantics, a retain_value on the tuple is equivalent to a retain value on
  // the tuple operand.
  if (auto *TI = dyn_cast<TupleInst>(V))
    if (SILValue NewValue = TI->getUniqueNonTrivialElt())
      return NewValue;

  return SILValue();
}

/// Return the underlying SILValue after stripping off SILArguments that can not
/// affect RC identity if our BB has only one predecessor.
SILValue
RCIdentityAnalysis::
stripRCIdentityPreservingArgs(SILValue V, unsigned RecursionDepth) {
  auto *A = dyn_cast<SILArgument>(V);
  if (!A) {
    return SILValue();
  }

  // If we already visited this BB, don't reprocess it since we have a cycle.
  if (!VisitedArgs.insert(A).second) {
    return SILValue();
  }

  // Ok, this is the first time that we have visited this BB. Get the
  // SILArgument's incoming values. If we don't have an incoming value for each
  // one of our predecessors, just return SILValue().
  llvm::SmallVector<SILValue, 8> IncomingValues;
  if (!A->getIncomingValues(IncomingValues) || IncomingValues.empty()) {
    return SILValue();
  }

  unsigned IVListSize = IncomingValues.size();

  // If we only have one incoming value, just return the identity root of that
  // incoming value. There can be no loop problems.
  if (IVListSize == 1) {
    return getRCIdentityRootInner(IncomingValues[0], RecursionDepth+1);
  }

  // Ok, we have multiple predecessors. First find the first non-payloaded enum.
  unsigned i = 0;
  for (; i < IVListSize && isNoPayloadEnum(IncomingValues[i]); ++i) {}

  // If we did not find any non-payloaded enum, there is no RC associated with
  // this Phi node. Just return SILValue().
  if (i == IVListSize)
    return SILValue();

  SILValue FirstIV = IncomingValues[i];

  // Strip off any non-argument instructions from IV. We know that
  while (SILValue NewIV = stripRCIdentityPreservingInsts(FirstIV))
    FirstIV = NewIV;

  // Then make sure that this incoming value is from a BB which is different
  // from our BB and dominates our BB. Otherwise, just return SILValue() there
  // is nothing we can do hter.
  DominanceInfo *DI = DA->getDomInfo(A->getFunction());
  if (!dominatesArgument(DI, A, FirstIV))
    return SILValue();

  // Ok, it is safe to continue stripping from this argument. Perform the
  // recursive stripping.
  FirstIV = getRCIdentityRootInner(FirstIV, RecursionDepth+1);
  while (i < IVListSize) {
    SILValue IV = IncomingValues[i++];

    // If IV is a no payload enum, we don't care about it. Skip it.
    if (isNoPayloadEnum(IV))
      continue;

    // Strip off any non-argument instructions from IV. We know that
    while (SILValue NewIV = stripRCIdentityPreservingInsts(IV))
      IV = NewIV;

    // Then make sure that this incoming value is from a BB which is different
    // from our BB and dominates our BB. Otherwise, just return SILValue() there
    // is nothing we can do hter.
    if (!dominatesArgument(DI, A, IV))
      return SILValue();

    // Ok, it is safe to continue stripping incoming values. Perform the
    // stripping and check if the stripped value equals FirstIV. If it is not
    // so, then bail. We found a conflicting value in our merging.
    if (getRCIdentityRootInner(IV, RecursionDepth+1) != FirstIV)
      return SILValue();
  }

  // Ok all our values match! Return FirstIV.
  return FirstIV;
}

llvm::cl::opt<bool> StripOffArgs(
    "enable-rc-identity-arg-strip", llvm::cl::init(true),
    llvm::cl::desc("Should RC identity try to strip off arguments"));

SILValue
RCIdentityAnalysis::
stripRCIdentityPreservingOps(SILValue V, unsigned RecursionDepth) {
  while (true) {
    // First strip off any RC identity preserving instructions. This is cheap.
    if (SILValue NewV = stripRCIdentityPreservingInsts(V)) {
      V = NewV;
      continue;
    }

    if (!StripOffArgs)
      break;

    // Once we have done all of the easy work, try to see if we can strip off
    // any RCIdentityPreserving args. This is potentially expensive since we
    // need to perform additional stripping on the argument provided to this
    // argument from each predecessor BB. There is a counter in
    // getRCIdentityRootInner that ensures we don't do too many.
    SILValue NewV = stripRCIdentityPreservingArgs(V, RecursionDepth);
    if (!NewV)
      break;

    V = NewV;
  }

  return V;
}

//===----------------------------------------------------------------------===//
//                              Main Entry Point
//===----------------------------------------------------------------------===//

SILValue RCIdentityAnalysis::getRCIdentityRootInner(SILValue V,
                                                    unsigned RecursionDepth) {
  // Only allow this method to be recursed on for a limited number of times to
  // make sure we don't explode compile time.
  if (RecursionDepth >= MaxRecursionDepth)
    return SILValue();

  // First check the cache.
  auto Pair = Cache.find(V);
  if (Pair != Cache.end())
    return Pair->second;

  SILValue NewValue = stripRCIdentityPreservingOps(V, RecursionDepth);
  if (!NewValue)
    return SILValue();

  // We can get back V if our analysis completely fails. There is no point in
  // storing this value into the cache so just return it.
  if (NewValue == V)
    return V;

  return Cache[V] = NewValue;
}

SILValue RCIdentityAnalysis::getRCIdentityRoot(SILValue V) {
  SILValue Root = getRCIdentityRootInner(V, 0);
  VisitedArgs.clear();

  // If we fail to find a root, return V.
  if (!Root)
    return V;

  return Root;
}

SILAnalysis *swift::createRCIdentityAnalysis(SILModule *M, SILPassManager *PM) {
  return new RCIdentityAnalysis(M, PM);
}
<|endoftext|>


<commit_before>/*
 * Vector.cpp
 *
 *  Created on: 18.01.2014
 *      Author: daniela
 */

#include "Vector.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <sstream>
#include <cstring>
#include <math.h>

Vector::Vector() {
	this->v1= 0;
	this->v2 = 0;
	this->v3 = 0;
}

Vector::Vector(double v1, double v2, double v3) {
	this->v1= v1;
	this->v2 = v2;
	this->v3 = v3;
}

double Vector::getV1() {
	return this->v1;
}

double Vector::getV2() {
	return this->v2;
}

double Vector::getV3() {
	return this->v3;
}

void Vector::setV1(double v1) {
	this->v1 = v1;
}

void Vector::setV2(double v2) {
	this->v2 = v2;
}

void Vector::setV3(double v3) {
	this->v3 = v3;
}

Vector Vector::add(Vector a) {
    double v1 = this->v1 + a.getV1();
    double v2 = this->v2 + a.getV2();
    double v3 = this->v3 + a.getV3();
    Vector v = Vector(v1, v2, v3);
    return v;
}

Vector Vector::mult(double a) {
    Vector v = Vector(this->v1 * a, this->v2 * a, this->v3 * a);
    return v;
}

Vector Vector::premult(Matrix A) {
    double a1 = v1 * A.getM11() + v2 * A.getM21() + v3 * A.getM31();
    double a2 = v1 * A.getM12() + v2 * A.getM22() + v3 * A.getM32();
    double a3 = v1 * A.getM13() + v2 * A.getM23() + v3 * A.getM33();
    Vector result = Vector(a1, a2, a3);
    return result;
}

Vector Vector::aftermult(Matrix A) {
    double a1 = v1 * A.getM11() + v2 * A.getM12() + v3 * A.getM13();
    double a2 = v1 * A.getM21() + v2 * A.getM22() + v3 * A.getM23();
    double a3 = v1 * A.getM31() + v2 * A.getM32() + v3 * A.getM33();
    Vector result = Vector(a1, a2, a3);
    return result;
}

double Vector::scalarMult(Vector a) {
    return (this->v1*a.getV1() + this->v2*a.getV2() + this->v3*a.getV3());
}

double Vector::getLength() {
    return sqrt((this->v1*this->v1 + this->v2*this->v2 + this->v3*this->v3));
}

void Vector::putVariable(std::string a, Engine *ep) {
    double datav1[1] = {v1};
    double datav2[1] = {v2};
    double datav3[1] = {v3};
    mxArray *v1 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v1), (void *)datav1, sizeof(datav1));
    std::string out = a + "1";
    engPutVariable(ep, out.c_str(), v1);
    mxArray *v2 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v2), (void *)datav2, sizeof(datav2));
    out = a + "2";
    engPutVariable(ep, out.c_str(), v2);
    mxArray *v3 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v3), (void *)datav3, sizeof(datav3));
    out = a + "3";
    engPutVariable(ep, out.c_str(), v3);
    out = a+" = [" + a + "1, " + a + "2, " + a + "3]";
    engEvalString(ep, out.c_str());
    mxDestroyArray(v1);
    mxDestroyArray(v2);
    mxDestroyArray(v3);
}

Vector Vector::cross(Vector v) {
    Vector cross = Vector(v.getV2()*v3 - v.getV3()*v2, v.getV3()*v1 - v.getV1()*v3, v.getV1()*v2 -v.getV2()*v1);
    return cross;
}

std::string Vector::toString() {
	std::stringstream ss;
	ss << v1 << "/" << v2 << "/" << v3;
	return ss.str();
}

bool Vector::isValid() {
	return !(isnan(v1) || isnan(v2) || isnan(v3));
}

bool Vector::isLinearDependent(Vector u) {
    // checking, if one vector value is 0, if the other is also 0
    if ( !(((v1 == 0) && (u.getV1() == 0)) || ((v1 != 0) && (u.getV1() != 0)))
        && (((v2 == 0) && (u.getV2() == 0)) || ((v1 != 0) && (u.getV2() != 0)))
        && (((v3 == 0) && (u.getV3() == 0)) || ((v1 != 0) && (u.getV3() != 0))) ) {
        return true;
    // checking, if two values of both vectors are 0 and the third is equal
    } else if ( (((v1 == 0) && (v2 == 0)) && (v3 = u.getV3())) || (((v1 == 0) && (v3 == 0)) && (v2 = u.getV2())) || (((v2 == 0) && (v3 == 0)) && (v1 = u.getV1())) ) {
        return true;
    } else if ((v1 == 0) && (v2/u.getV2() == v3/ u.getV3())) {
        return true;
    } else if ((v2 == 0) && (v1/u.getV1() == v3/u.getV3())) {
        return true;
    } else if ((v3 == 0) && (v1/u.getV1() == v2/u.getV2())) {
        return true;
    } else if ((v1/u.getV1() == v2/u.getV2()) && (v1/u.getV1() == v3/u.getV3())) {
        return true;
    } else {
        return false;
    }
}
<commit_msg>Added check for valid to isValid<commit_after>/*
 * Vector.cpp
 *
 *  Created on: 18.01.2014
 *      Author: daniela
 */

#include "Vector.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#include <sstream>
#include <cstring>
#include <math.h>

Vector::Vector() {
	this->v1= 0;
	this->v2 = 0;
	this->v3 = 0;
}

Vector::Vector(double v1, double v2, double v3) {
	this->v1= v1;
	this->v2 = v2;
	this->v3 = v3;
}

double Vector::getV1() {
	return this->v1;
}

double Vector::getV2() {
	return this->v2;
}

double Vector::getV3() {
	return this->v3;
}

void Vector::setV1(double v1) {
	this->v1 = v1;
}

void Vector::setV2(double v2) {
	this->v2 = v2;
}

void Vector::setV3(double v3) {
	this->v3 = v3;
}

Vector Vector::add(Vector a) {
    double v1 = this->v1 + a.getV1();
    double v2 = this->v2 + a.getV2();
    double v3 = this->v3 + a.getV3();
    Vector v = Vector(v1, v2, v3);
    return v;
}

Vector Vector::mult(double a) {
    Vector v = Vector(this->v1 * a, this->v2 * a, this->v3 * a);
    return v;
}

Vector Vector::premult(Matrix A) {
    double a1 = v1 * A.getM11() + v2 * A.getM21() + v3 * A.getM31();
    double a2 = v1 * A.getM12() + v2 * A.getM22() + v3 * A.getM32();
    double a3 = v1 * A.getM13() + v2 * A.getM23() + v3 * A.getM33();
    Vector result = Vector(a1, a2, a3);
    return result;
}

Vector Vector::aftermult(Matrix A) {
    double a1 = v1 * A.getM11() + v2 * A.getM12() + v3 * A.getM13();
    double a2 = v1 * A.getM21() + v2 * A.getM22() + v3 * A.getM23();
    double a3 = v1 * A.getM31() + v2 * A.getM32() + v3 * A.getM33();
    Vector result = Vector(a1, a2, a3);
    return result;
}

double Vector::scalarMult(Vector a) {
    return (this->v1*a.getV1() + this->v2*a.getV2() + this->v3*a.getV3());
}

double Vector::getLength() {
    return sqrt((this->v1*this->v1 + this->v2*this->v2 + this->v3*this->v3));
}

void Vector::putVariable(std::string a, Engine *ep) {
    double datav1[1] = {v1};
    double datav2[1] = {v2};
    double datav3[1] = {v3};
    mxArray *v1 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v1), (void *)datav1, sizeof(datav1));
    std::string out = a + "1";
    engPutVariable(ep, out.c_str(), v1);
    mxArray *v2 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v2), (void *)datav2, sizeof(datav2));
    out = a + "2";
    engPutVariable(ep, out.c_str(), v2);
    mxArray *v3 = mxCreateDoubleMatrix(1, 1, mxREAL);
    memcpy((void *)mxGetPr(v3), (void *)datav3, sizeof(datav3));
    out = a + "3";
    engPutVariable(ep, out.c_str(), v3);
    out = a+" = [" + a + "1, " + a + "2, " + a + "3]";
    engEvalString(ep, out.c_str());
    mxDestroyArray(v1);
    mxDestroyArray(v2);
    mxDestroyArray(v3);
}

Vector Vector::cross(Vector v) {
    Vector cross = Vector(v.getV2()*v3 - v.getV3()*v2, v.getV3()*v1 - v.getV1()*v3, v.getV1()*v2 -v.getV2()*v1);
    return cross;
}

std::string Vector::toString() {
	std::stringstream ss;
	ss << v1 << "/" << v2 << "/" << v3;
	return ss.str();
}

bool Vector::isValid() {
	return !(isnan(v1) || isnan(v2) || isnan(v3)) && valid;
}

bool Vector::isLinearDependent(Vector u) {
    // checking, if one vector value is 0, if the other is also 0
    if ( !(((v1 == 0) && (u.getV1() == 0)) || ((v1 != 0) && (u.getV1() != 0)))
        && (((v2 == 0) && (u.getV2() == 0)) || ((v1 != 0) && (u.getV2() != 0)))
        && (((v3 == 0) && (u.getV3() == 0)) || ((v1 != 0) && (u.getV3() != 0))) ) {
        return true;
    // checking, if two values of both vectors are 0 and the third is equal
    } else if ( (((v1 == 0) && (v2 == 0)) && (v3 = u.getV3())) || (((v1 == 0) && (v3 == 0)) && (v2 = u.getV2())) || (((v2 == 0) && (v3 == 0)) && (v1 = u.getV1())) ) {
        return true;
    } else if ((v1 == 0) && (v2/u.getV2() == v3/ u.getV3())) {
        return true;
    } else if ((v2 == 0) && (v1/u.getV1() == v3/u.getV3())) {
        return true;
    } else if ((v3 == 0) && (v1/u.getV1() == v2/u.getV2())) {
        return true;
    } else if ((v1/u.getV1() == v2/u.getV2()) && (v1/u.getV1() == v3/u.getV3())) {
        return true;
    } else {
        return false;
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <sstream>
#include <cstring> //strerror()
#include <fstream>
#include <regex>

#include <fcntl.h> //open, read, lseek
#include <sys/ptrace.h> //ptrace()
#include <sys/wait.h> //waitpid()
#include <dirent.h> //read directory
#include <signal.h> // kill

#include "med/MedCommon.hpp"
#include "med/MedException.hpp"
#include "med/Process.hpp"
#include "med/ScanParser.hpp"
#include "mem/StringUtil.hpp"

using namespace std;

int hexStrToInt(const string& str) {
  auto trimmed = StringUtil::toLower(StringUtil::trim(str));
  if (trimmed == "0") return 0;
  else if (trimmed == "1") return 1;
  else if (trimmed == "2") return 2;
  else if (trimmed == "3") return 3;
  else if (trimmed == "4") return 4;
  else if (trimmed == "5") return 5;
  else if (trimmed == "6") return 6;
  else if (trimmed == "7") return 7;
  else if (trimmed == "8") return 8;
  else if (trimmed == "9") return 9;
  else if (trimmed == "a") return 10;
  else if (trimmed == "b") return 11;
  else if (trimmed == "c") return 12;
  else if (trimmed == "d") return 13;
  else if (trimmed == "e") return 14;
  else if (trimmed == "f") return 15;
  return -1;
}

/**
 * @brief Convert hexadecimal string to integer value
 */
long hexToInt(string str) {
  stringstream ss(str);
  long ret = -1;
  ss >> hex >> ret;
  if(ss.fail()) {
    throw MedException(string("Error input: ") + str);
  }

  return ret;
}

/**
 * @brief Convert long integer to hex string
 */
string intToHex(long hex) {
  char str[64];
  sprintf(str,"%p",(void*)hex);
  return string(str);
}

ScanType stringToScanType(const string& scanType) {
  if (scanType == SCAN_TYPE_INT_8) {
    return Int8;
  }
  else if (scanType == SCAN_TYPE_INT_16) {
    return Int16;
  }
  else if (scanType == SCAN_TYPE_INT_32) {
    return Int32;
  }
  else if (scanType == SCAN_TYPE_PTR_32) {
    return Ptr32;
  }
  else if (scanType == SCAN_TYPE_PTR_64) {
    return Ptr64;
  }
  else if (scanType == SCAN_TYPE_FLOAT_32) {
    return Float32;
  }
  else if (scanType == SCAN_TYPE_FLOAT_64) {
    return Float64;
  }
  else if (scanType == SCAN_TYPE_STRING) {
    return String;
  }
  return Unknown;
}

string scanTypeToString(const ScanType& scanType) {
  string ret;
  switch (scanType) {
  case Int8:
    ret = SCAN_TYPE_INT_8;
    break;
  case Int16:
    ret = SCAN_TYPE_INT_16;
    break;
  case Int32:
    ret = SCAN_TYPE_INT_32;
    break;
  case Ptr32:
    ret = SCAN_TYPE_PTR_32;
    break;
  case Ptr64:
    ret = SCAN_TYPE_PTR_64;
    break;
  case Float32:
    ret = SCAN_TYPE_FLOAT_32;
    break;
  case Float64:
    ret = SCAN_TYPE_FLOAT_64;
    break;
  case String:
    ret = SCAN_TYPE_STRING;
    break;
  default:
    ret = SCAN_TYPE_UNKNOWN;
  }
  return ret;
}

int scanTypeToSize(const ScanType& type) {
  int ret = 0;
  switch (type) {
  case Int8:
    ret = sizeof(uint8_t);
    break;
  case Int16:
    ret = sizeof(uint16_t);
    break;
  case Int32:
  case Ptr32:
    ret = sizeof(uint32_t);
    break;
  case Ptr64:
    ret = sizeof(uint64_t);
    break;
  case Float32:
    ret = sizeof(float);
    break;
  case Float64:
    ret = sizeof(double);
    break;
  case String:
    ret = MAX_STRING_SIZE;
    break;
  case Unknown:
    ret = 0;
  }
  return ret;
}

int scanTypeToSize(const string& type) {
  return scanTypeToSize(stringToScanType(type));
}

/**
 * @brief Print the hexadecimal data
 */
void printHex(FILE* file,void* addr,int size) {
  for(int i=0;i<size;i++) {
    fprintf(file,"%02x ",((uint8_t*)addr)[i]);
  }
}

Maps getMaps(pid_t pid) {
  Maps maps;

  //Get the region from /proc/pid/maps
  char filename[128];
  sprintf(filename,"/proc/%d/maps",pid);
  FILE* file;
  file = fopen(filename,"r");
  if(!file) {
    printf("Failed open maps: %s\n",filename);
    exit(1);
  }

  char useless[64];
  Address start, end;
  char rd, wr;
  unsigned int inode;
  char sp; //shared or private
  char fname[128];

  //Get line
  char line[256];

  while (fgets(line, 255, file)) {
    //parse line
    //the empty pathname has to be scan also
    if (sscanf(line, "%lx-%lx %c%c%c%c %8s %5s %u %127s",
              &start, &end,
              &rd, &wr, useless, &sp,
              useless, useless, &inode, fname) < 9) {
      continue;
    }

    if (rd == 'r' && ((end - start) > 0)) {
      AddressPair pair(start, end);
      maps.push(pair);
    }
  }

  fclose(file);

  return maps;
}

/**
 * Open the /proc/[pid]/mem
 * @return file descriptor
 */
int getMem(pid_t pid) {
  char filename[32];
  sprintf(filename, "/proc/%d/mem", pid);
  int ret = open(filename, O_RDONLY);
  if (ret == -1) {
    printf("Open failed: %s\n", strerror(errno));
  }
  return ret;
}

/**
 * Attach PID
 */
pid_t pidAttach(pid_t pid) {
  if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1L) {
    fprintf(stderr, "Failed attach: %s\n", strerror(errno));
    throw MedException("Failed attach");
  }

  int status;
  if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) {
    fprintf(stderr, "Error waiting: %s\n", strerror(errno));
    throw MedException("Error waiting");
  }

  return pid;
}

pid_t pidDetach(pid_t pid) {
  if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1L) {
    fprintf(stderr, "Failed detach: %s\n", strerror(errno));
    throw MedException("Failed detach");
  }
  return -1;
}

char getPidStatus(const char* stat) {
  string s = stat;
  regex reg("\\d+ \\(.*?\\) (\\w) \\d+");
  smatch m;
  if (regex_search(s, m, reg)) {
    return m.str(1).at(0);
  }
  return 'X';
}

bool isPidSuspended(pid_t pid) {
  char filename[128];
  sprintf(filename, "/proc/%d/stat", pid);
  FILE* file;
  file = fopen(filename, "r");
  if (!file) {
    printf("Failed open stat: %s\n", filename);
    exit(1);
  }
  char line[256];
  fgets(line, 255, file);
  fclose(file);

  char state = getPidStatus(line);
  if (state == 'T' || state == 't') {
    return true;
  }
  return false;
}

int pidResume(pid_t pid) {
  return kill(pid, SIGCONT);
}

int pidStop(pid_t pid) {
  return kill(pid, SIGSTOP);
}

/**
 * Convert the size to padded word size.
 */
int padWordSize(int x) {
  if(x % sizeof(Address))
    return x + sizeof(Address) - x % sizeof(Address);
  return x;
}

/**
 * Get the list of PID
 * This is done by accessing the /proc and /proc/PID and /proc/PID/cmdline
 * The list suppose to be in the descending order
 */
vector<Process> pidList() {
  //Get directories
  vector<Process> pids;

  DIR *d;
  struct dirent *dir;
  d = opendir("/proc");
  if (d) {
    while ((dir = readdir(d)) != NULL) {
      if (isdigit(dir->d_name[0])) {
        string cmd = pidName(dir->d_name);
        if (cmd.length()) {
          Process proc;
          proc.pid = dir->d_name;
          proc.cmdline = cmd;
          pids.push_back(proc);
        }

      }
    }
    closedir(d);
  }
  return pids;
}

/**
 * Get the cmdline from PID
 */
string pidName(const string& pid) {
  string ret;
  ifstream ifile;
  ifile.open(string("/proc/") + pid + "/cmdline");
  if(ifile.fail()) {
    return "";
  }
  getline(ifile, ret);
  ifile.close();

  return ret;
}

/**
 * This will just perform the unlock by force
 */
void tryUnlock(std::mutex &mutex) {
  mutex.try_lock();
  mutex.unlock();
}

void stringToMemory(const string& str, const ScanType& type, Byte* buffer) {
  if (isHexString(str)) {
    return hexStringToMemory(str, type, buffer);
  }

  stringstream ss(str);

  int temp;
  switch (type) {
  case Int8:
    ss >> dec >> temp; //Because it does not handle the uint8_t correctly as integer, but a character.
    *(uint8_t*)buffer = (uint8_t)temp;
    break;
  case Int16:
    ss >> dec >> *(uint16_t*)buffer;
    break;
  case Int32:
  case Ptr32:
    ss >> dec >> *(uint32_t*)buffer;
    break;
  case Ptr64:
    ss >> dec >> *(uint64_t*)buffer;
    break;
  case Float32:
    ss >> dec >> *(float*)buffer;
    break;
  case Float64:
    ss >> dec >> *(double*)buffer;
    break;
  case String:
    printf("Warning: stringToMemory with String type\n");
    break;
  case Unknown:
    break;
  }
  if(ss.fail()) {
    printf("stringToMemory Error input: %s\n", str.c_str());
  }
}

void stringToMemory(const string& str, const string& type, Byte* buffer) {
  ScanType scanType = stringToScanType(type);
  stringToMemory(str, scanType, buffer);
}

bool isHexString(const string& str) {
  regex reg("^0x[0-9a-fA-F]+");
  return regex_match(str, reg);
}

void hexStringToMemory(const string& str, const ScanType& type, Byte* buffer) {
  regex reg("^0x");
  string sanitized = regex_replace(str, reg, "");
  int length = scanTypeToSize(type) * 2;

  int indexStart = std::max((int)(sanitized.length() - length), 0);
  sanitized = sanitized.substr(indexStart, length);

  stringstream ss(sanitized);
  int temp;
  switch (type) {
  case Int8:
    ss >> hex >> temp;
    *(uint8_t*)buffer = (uint8_t)temp;
    break;
  case Int16:
    ss >> hex >> *(uint16_t*)buffer;
    break;
  case Int32:
  case Ptr32:
    ss >> hex >> *(uint32_t*)buffer;
    break;
  case Ptr64:
    ss >> hex >> *(uint64_t*)buffer;
    break;
  case Float32:
    ss >> hex >> *(float*)buffer;
    break;
  case Float64:
    ss >> hex >> *(double*)buffer;
    break;
  case String:
    printf("Warning: stringToMemory with String type\n");
    break;
  case Unknown:
    break;
  }
  if(ss.fail()) {
    printf("hexStringToMemory Error input: %s\n", str.c_str());
  }
}
<commit_msg>Revert wr == 'w'<commit_after>#include <iostream>
#include <sstream>
#include <cstring> //strerror()
#include <fstream>
#include <regex>

#include <fcntl.h> //open, read, lseek
#include <sys/ptrace.h> //ptrace()
#include <sys/wait.h> //waitpid()
#include <dirent.h> //read directory
#include <signal.h> // kill

#include "med/MedCommon.hpp"
#include "med/MedException.hpp"
#include "med/Process.hpp"
#include "med/ScanParser.hpp"
#include "mem/StringUtil.hpp"

using namespace std;

int hexStrToInt(const string& str) {
  auto trimmed = StringUtil::toLower(StringUtil::trim(str));
  if (trimmed == "0") return 0;
  else if (trimmed == "1") return 1;
  else if (trimmed == "2") return 2;
  else if (trimmed == "3") return 3;
  else if (trimmed == "4") return 4;
  else if (trimmed == "5") return 5;
  else if (trimmed == "6") return 6;
  else if (trimmed == "7") return 7;
  else if (trimmed == "8") return 8;
  else if (trimmed == "9") return 9;
  else if (trimmed == "a") return 10;
  else if (trimmed == "b") return 11;
  else if (trimmed == "c") return 12;
  else if (trimmed == "d") return 13;
  else if (trimmed == "e") return 14;
  else if (trimmed == "f") return 15;
  return -1;
}

/**
 * @brief Convert hexadecimal string to integer value
 */
long hexToInt(string str) {
  stringstream ss(str);
  long ret = -1;
  ss >> hex >> ret;
  if(ss.fail()) {
    throw MedException(string("Error input: ") + str);
  }

  return ret;
}

/**
 * @brief Convert long integer to hex string
 */
string intToHex(long hex) {
  char str[64];
  sprintf(str,"%p",(void*)hex);
  return string(str);
}

ScanType stringToScanType(const string& scanType) {
  if (scanType == SCAN_TYPE_INT_8) {
    return Int8;
  }
  else if (scanType == SCAN_TYPE_INT_16) {
    return Int16;
  }
  else if (scanType == SCAN_TYPE_INT_32) {
    return Int32;
  }
  else if (scanType == SCAN_TYPE_PTR_32) {
    return Ptr32;
  }
  else if (scanType == SCAN_TYPE_PTR_64) {
    return Ptr64;
  }
  else if (scanType == SCAN_TYPE_FLOAT_32) {
    return Float32;
  }
  else if (scanType == SCAN_TYPE_FLOAT_64) {
    return Float64;
  }
  else if (scanType == SCAN_TYPE_STRING) {
    return String;
  }
  return Unknown;
}

string scanTypeToString(const ScanType& scanType) {
  string ret;
  switch (scanType) {
  case Int8:
    ret = SCAN_TYPE_INT_8;
    break;
  case Int16:
    ret = SCAN_TYPE_INT_16;
    break;
  case Int32:
    ret = SCAN_TYPE_INT_32;
    break;
  case Ptr32:
    ret = SCAN_TYPE_PTR_32;
    break;
  case Ptr64:
    ret = SCAN_TYPE_PTR_64;
    break;
  case Float32:
    ret = SCAN_TYPE_FLOAT_32;
    break;
  case Float64:
    ret = SCAN_TYPE_FLOAT_64;
    break;
  case String:
    ret = SCAN_TYPE_STRING;
    break;
  default:
    ret = SCAN_TYPE_UNKNOWN;
  }
  return ret;
}

int scanTypeToSize(const ScanType& type) {
  int ret = 0;
  switch (type) {
  case Int8:
    ret = sizeof(uint8_t);
    break;
  case Int16:
    ret = sizeof(uint16_t);
    break;
  case Int32:
  case Ptr32:
    ret = sizeof(uint32_t);
    break;
  case Ptr64:
    ret = sizeof(uint64_t);
    break;
  case Float32:
    ret = sizeof(float);
    break;
  case Float64:
    ret = sizeof(double);
    break;
  case String:
    ret = MAX_STRING_SIZE;
    break;
  case Unknown:
    ret = 0;
  }
  return ret;
}

int scanTypeToSize(const string& type) {
  return scanTypeToSize(stringToScanType(type));
}

/**
 * @brief Print the hexadecimal data
 */
void printHex(FILE* file,void* addr,int size) {
  for(int i=0;i<size;i++) {
    fprintf(file,"%02x ",((uint8_t*)addr)[i]);
  }
}

Maps getMaps(pid_t pid) {
  Maps maps;

  //Get the region from /proc/pid/maps
  char filename[128];
  sprintf(filename,"/proc/%d/maps",pid);
  FILE* file;
  file = fopen(filename,"r");
  if(!file) {
    printf("Failed open maps: %s\n",filename);
    exit(1);
  }

  char useless[64];
  Address start, end;
  char rd, wr;
  unsigned int inode;
  char sp; //shared or private
  char fname[128];

  //Get line
  char line[256];

  while (fgets(line, 255, file)) {
    //parse line
    //the empty pathname has to be scan also
    if (sscanf(line, "%lx-%lx %c%c%c%c %8s %5s %u %127s",
              &start, &end,
              &rd, &wr, useless, &sp,
              useless, useless, &inode, fname) < 9) {
      continue;
    }

    if (rd == 'r' && wr == 'w' && ((end - start) > 0)) {
      AddressPair pair(start, end);
      maps.push(pair);
    }
  }

  fclose(file);

  return maps;
}

/**
 * Open the /proc/[pid]/mem
 * @return file descriptor
 */
int getMem(pid_t pid) {
  char filename[32];
  sprintf(filename, "/proc/%d/mem", pid);
  int ret = open(filename, O_RDONLY);
  if (ret == -1) {
    printf("Open failed: %s\n", strerror(errno));
  }
  return ret;
}

/**
 * Attach PID
 */
pid_t pidAttach(pid_t pid) {
  if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1L) {
    fprintf(stderr, "Failed attach: %s\n", strerror(errno));
    throw MedException("Failed attach");
  }

  int status;
  if (waitpid(pid, &status, 0) == -1 || !WIFSTOPPED(status)) {
    fprintf(stderr, "Error waiting: %s\n", strerror(errno));
    throw MedException("Error waiting");
  }

  return pid;
}

pid_t pidDetach(pid_t pid) {
  if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1L) {
    fprintf(stderr, "Failed detach: %s\n", strerror(errno));
    throw MedException("Failed detach");
  }
  return -1;
}

char getPidStatus(const char* stat) {
  string s = stat;
  regex reg("\\d+ \\(.*?\\) (\\w) \\d+");
  smatch m;
  if (regex_search(s, m, reg)) {
    return m.str(1).at(0);
  }
  return 'X';
}

bool isPidSuspended(pid_t pid) {
  char filename[128];
  sprintf(filename, "/proc/%d/stat", pid);
  FILE* file;
  file = fopen(filename, "r");
  if (!file) {
    printf("Failed open stat: %s\n", filename);
    exit(1);
  }
  char line[256];
  fgets(line, 255, file);
  fclose(file);

  char state = getPidStatus(line);
  if (state == 'T' || state == 't') {
    return true;
  }
  return false;
}

int pidResume(pid_t pid) {
  return kill(pid, SIGCONT);
}

int pidStop(pid_t pid) {
  return kill(pid, SIGSTOP);
}

/**
 * Convert the size to padded word size.
 */
int padWordSize(int x) {
  if(x % sizeof(Address))
    return x + sizeof(Address) - x % sizeof(Address);
  return x;
}

/**
 * Get the list of PID
 * This is done by accessing the /proc and /proc/PID and /proc/PID/cmdline
 * The list suppose to be in the descending order
 */
vector<Process> pidList() {
  //Get directories
  vector<Process> pids;

  DIR *d;
  struct dirent *dir;
  d = opendir("/proc");
  if (d) {
    while ((dir = readdir(d)) != NULL) {
      if (isdigit(dir->d_name[0])) {
        string cmd = pidName(dir->d_name);
        if (cmd.length()) {
          Process proc;
          proc.pid = dir->d_name;
          proc.cmdline = cmd;
          pids.push_back(proc);
        }

      }
    }
    closedir(d);
  }
  return pids;
}

/**
 * Get the cmdline from PID
 */
string pidName(const string& pid) {
  string ret;
  ifstream ifile;
  ifile.open(string("/proc/") + pid + "/cmdline");
  if(ifile.fail()) {
    return "";
  }
  getline(ifile, ret);
  ifile.close();

  return ret;
}

/**
 * This will just perform the unlock by force
 */
void tryUnlock(std::mutex &mutex) {
  mutex.try_lock();
  mutex.unlock();
}

void stringToMemory(const string& str, const ScanType& type, Byte* buffer) {
  if (isHexString(str)) {
    return hexStringToMemory(str, type, buffer);
  }

  stringstream ss(str);

  int temp;
  switch (type) {
  case Int8:
    ss >> dec >> temp; //Because it does not handle the uint8_t correctly as integer, but a character.
    *(uint8_t*)buffer = (uint8_t)temp;
    break;
  case Int16:
    ss >> dec >> *(uint16_t*)buffer;
    break;
  case Int32:
  case Ptr32:
    ss >> dec >> *(uint32_t*)buffer;
    break;
  case Ptr64:
    ss >> dec >> *(uint64_t*)buffer;
    break;
  case Float32:
    ss >> dec >> *(float*)buffer;
    break;
  case Float64:
    ss >> dec >> *(double*)buffer;
    break;
  case String:
    printf("Warning: stringToMemory with String type\n");
    break;
  case Unknown:
    break;
  }
  if(ss.fail()) {
    printf("stringToMemory Error input: %s\n", str.c_str());
  }
}

void stringToMemory(const string& str, const string& type, Byte* buffer) {
  ScanType scanType = stringToScanType(type);
  stringToMemory(str, scanType, buffer);
}

bool isHexString(const string& str) {
  regex reg("^0x[0-9a-fA-F]+");
  return regex_match(str, reg);
}

void hexStringToMemory(const string& str, const ScanType& type, Byte* buffer) {
  regex reg("^0x");
  string sanitized = regex_replace(str, reg, "");
  int length = scanTypeToSize(type) * 2;

  int indexStart = std::max((int)(sanitized.length() - length), 0);
  sanitized = sanitized.substr(indexStart, length);

  stringstream ss(sanitized);
  int temp;
  switch (type) {
  case Int8:
    ss >> hex >> temp;
    *(uint8_t*)buffer = (uint8_t)temp;
    break;
  case Int16:
    ss >> hex >> *(uint16_t*)buffer;
    break;
  case Int32:
  case Ptr32:
    ss >> hex >> *(uint32_t*)buffer;
    break;
  case Ptr64:
    ss >> hex >> *(uint64_t*)buffer;
    break;
  case Float32:
    ss >> hex >> *(float*)buffer;
    break;
  case Float64:
    ss >> hex >> *(double*)buffer;
    break;
  case String:
    printf("Warning: stringToMemory with String type\n");
    break;
  case Unknown:
    break;
  }
  if(ss.fail()) {
    printf("hexStringToMemory Error input: %s\n", str.c_str());
  }
}
<|endoftext|>


<commit_before>//===-- ElimAvailExtern.cpp - DCE unreachable internal functions ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate available external global
// definitions from the program, turning them into declarations.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/CtorUtils.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include "llvm/Pass.h"
using namespace llvm;

#define DEBUG_TYPE "elim-avail-extern"

STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumVariables, "Number of global variables removed");

namespace {
  struct EliminateAvailableExternally : public ModulePass {
    static char ID; // Pass identification, replacement for typeid
    EliminateAvailableExternally() : ModulePass(ID) {
      initializeEliminateAvailableExternallyPass(
          *PassRegistry::getPassRegistry());
    }

    // run - Do the EliminateAvailableExternally pass on the specified module,
    // optionally updating the specified callgraph to reflect the changes.
    //
    bool runOnModule(Module &M) override;
  };
}

char EliminateAvailableExternally::ID = 0;
INITIALIZE_PASS(EliminateAvailableExternally, "elim-avail-extern",
                "Eliminate Available Externally Globals", false, false)

ModulePass *llvm::createEliminateAvailableExternallyPass() {
  return new EliminateAvailableExternally();
}

bool EliminateAvailableExternally::runOnModule(Module &M) {
  bool Changed = false;

  // Drop initializers of available externally global variables.
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (!I->hasAvailableExternallyLinkage())
      continue;
    if (I->hasInitializer()) {
      Constant *Init = I->getInitializer();
      I->setInitializer(nullptr);
      if (isSafeToDestroyConstant(Init))
        Init->destroyConstant();
    }
    I->removeDeadConstantUsers();
    I->setLinkage(GlobalValue::ExternalLinkage);
    NumVariables++;
  }

  // Drop the bodies of available externally functions.
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    if (!I->hasAvailableExternallyLinkage())
      continue;
    if (!I->isDeclaration())
      // This will set the linkage to external
      I->deleteBody();
    I->removeDeadConstantUsers();
    NumFunctions++;
  }

  return Changed;
}
<commit_msg>Remove two unused includes and C++11 rangify for loops.<commit_after>//===-- ElimAvailExtern.cpp - DCE unreachable internal functions ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This transform is designed to eliminate available external global
// definitions from the program, turning them into declarations.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
#include "llvm/Pass.h"
using namespace llvm;

#define DEBUG_TYPE "elim-avail-extern"

STATISTIC(NumFunctions, "Number of functions removed");
STATISTIC(NumVariables, "Number of global variables removed");

namespace {
  struct EliminateAvailableExternally : public ModulePass {
    static char ID; // Pass identification, replacement for typeid
    EliminateAvailableExternally() : ModulePass(ID) {
      initializeEliminateAvailableExternallyPass(
          *PassRegistry::getPassRegistry());
    }

    // run - Do the EliminateAvailableExternally pass on the specified module,
    // optionally updating the specified callgraph to reflect the changes.
    //
    bool runOnModule(Module &M) override;
  };
}

char EliminateAvailableExternally::ID = 0;
INITIALIZE_PASS(EliminateAvailableExternally, "elim-avail-extern",
                "Eliminate Available Externally Globals", false, false)

ModulePass *llvm::createEliminateAvailableExternallyPass() {
  return new EliminateAvailableExternally();
}

bool EliminateAvailableExternally::runOnModule(Module &M) {
  bool Changed = false;

  // Drop initializers of available externally global variables.
  for (GlobalVariable &GV :M.globals()) {
    if (!GV.hasAvailableExternallyLinkage())
      continue;
    if (GV.hasInitializer()) {
      Constant *Init = GV.getInitializer();
      GV.setInitializer(nullptr);
      if (isSafeToDestroyConstant(Init))
        Init->destroyConstant();
    }
    GV.removeDeadConstantUsers();
    GV.setLinkage(GlobalValue::ExternalLinkage);
    NumVariables++;
  }

  // Drop the bodies of available externally functions.
  for (Function &F : M) {
    if (!F.hasAvailableExternallyLinkage())
      continue;
    if (!F.isDeclaration())
      // This will set the linkage to external
      F.deleteBody();
    F.removeDeadConstantUsers();
    NumFunctions++;
  }

  return Changed;
}
<|endoftext|>


<commit_before>//===- ConstantProp.cpp - Code to perform Constant Propogation ------------===//
//
// This file implements constant propogation and merging:
//
// Specifically, this:
//   * Folds multiple identical constants in the constant pool together
//     Note that if one is named and the other is not, that the result gets the
//     original name.
//   * Converts instructions like "add int %1, %2" into a direct def of %3 in
//     the constant pool
//   * Converts conditional branches on a constant boolean value into direct
//     branches.
//   * Converts phi nodes with one incoming def to the incoming def directly
//   . Converts switch statements with one entry into a test & conditional
//     branch
//   . Converts switches on constant values into an unconditional branch.
//
// Notice that:
//   * This pass has a habit of making definitions be dead.  It is a good idea
//     to to run a DCE pass sometime after running this pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/BasicBlock.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/ConstantPool.h"
#include "llvm/Opt/AllOpts.h"
#include "llvm/Opt/ConstantHandling.h"

// Merge identical constant values in the constant pool.
//
// TODO: We can do better than this simplistic N^2 algorithm...
//
static bool MergeConstantPoolReferences(ConstantPool &CP) {
  bool Modified = false;
  for (ConstantPool::plane_iterator PI = CP.begin(); PI != CP.end(); ++PI) {
    for (ConstantPool::PlaneType::iterator I = (*PI)->begin();
	 I != (*PI)->end(); I++) {
      ConstPoolVal *C = *I;

      ConstantPool::PlaneType::iterator J = I;
      for (++J; J != (*PI)->end(); J++) {
	if (C->equals(*J)) {
	  Modified = true;
	  // Okay we know that *I == *J.  So now we need to make all uses of *I
	  // point to *J.
	  //
	  C->replaceAllUsesWith(*J);

	  (*PI)->remove(I); // Remove C from constant pool...

	  if (C->hasName() && !(*J)->hasName())  // The merged constant inherits
	    (*J)->setName(C->getName());         // the old name...

	  delete C;                              // Delete the constant itself.
	  break;  // Break out of inner for loop
	}
      }
    }
  }
  return Modified;
}

inline static bool
ConstantFoldUnaryInst(Method *M, Method::inst_iterator &DI,
                      UnaryOperator *Op, ConstPoolVal *D) {
  ConstPoolVal *ReplaceWith = 0;

  switch (Op->getInstType()) {
  case Instruction::Not:  ReplaceWith = !*D; break;
  case Instruction::Neg:  ReplaceWith = -*D; break;
  }

  if (!ReplaceWith) return false;   // Nothing new to change...

  // Add the new value to the constant pool...
  M->getConstantPool().insert(ReplaceWith);

  // Replaces all of the uses of a variable with uses of the constant.
  Op->replaceAllUsesWith(ReplaceWith);

  // Remove the operator from the list of definitions...
  Op->getParent()->getInstList().remove(DI.getInstructionIterator());

  // The new constant inherits the old name of the operator...
  if (Op->hasName()) ReplaceWith->setName(Op->getName());

  // Delete the operator now...
  delete Op;
  return true;
}

inline static bool
ConstantFoldBinaryInst(Method *M, Method::inst_iterator &DI,
		       BinaryOperator *Op,
		       ConstPoolVal *D1, ConstPoolVal *D2) {
  ConstPoolVal *ReplaceWith = 0;

  switch (Op->getInstType()) {
  case Instruction::Add:     ReplaceWith = *D1 + *D2; break;
  case Instruction::Sub:     ReplaceWith = *D1 - *D2; break;

  case Instruction::SetEQ:   ReplaceWith = *D1 == *D2; break;
  case Instruction::SetNE:   ReplaceWith = *D1 != *D2; break;
  case Instruction::SetLE:   ReplaceWith = *D1 <= *D2; break;
  case Instruction::SetGE:   ReplaceWith = *D1 >= *D2; break;
  case Instruction::SetLT:   ReplaceWith = *D1 <  *D2; break;
  case Instruction::SetGT:   ReplaceWith = *D1 >  *D2; break;
  }

  if (!ReplaceWith) return false;   // Nothing new to change...

  // Add the new value to the constant pool...
  M->getConstantPool().insert(ReplaceWith);

  // Replaces all of the uses of a variable with uses of the constant.
  Op->replaceAllUsesWith(ReplaceWith);

  // Remove the operator from the list of definitions...
  Op->getParent()->getInstList().remove(DI.getInstructionIterator());

  // The new constant inherits the old name of the operator...
  if (Op->hasName()) ReplaceWith->setName(Op->getName());

  // Delete the operator now...
  delete Op;
  return true;
}

inline static bool ConstantFoldTerminator(TerminatorInst *T) {
  // Branch - See if we are conditional jumping on constant
  if (T->getInstType() == Instruction::Br) {
    BranchInst *BI = (BranchInst*)T;
    if (!BI->isUnconditional() &&              // Are we branching on constant?
        BI->getOperand(2)->getValueType() == Value::ConstantVal) {
      // YES.  Change to unconditional branch...
      ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
      Value *Destination = BI->getOperand(Cond->getValue() ? 0 : 1);

      BI->setOperand(0, Destination);  // Set the unconditional destination
      BI->setOperand(1, 0);            // Clear the conditional destination
      BI->setOperand(2, 0);            // Clear the condition...
      return true;
    }
  }
  return false;
}

// ConstantFoldInstruction - If an instruction references constants, try to fold
// them together...
//
inline static bool
ConstantFoldInstruction(Method *M, Method::inst_iterator &II) {
  Instruction *Inst = *II;
  if (Inst->isBinaryOp()) {
    Value *D1, *D2;
    if (((D1 = Inst->getOperand(0))->getValueType() == Value::ConstantVal) &
        ((D2 = Inst->getOperand(1))->getValueType() == Value::ConstantVal))
      return ConstantFoldBinaryInst(M, II, (BinaryOperator*)Inst,
                                    (ConstPoolVal*)D1, (ConstPoolVal*)D2);

  } else if (Inst->isUnaryOp()) {
    Value *D;
    if ((D = Inst->getOperand(0))->getValueType() == Value::ConstantVal)
      return ConstantFoldUnaryInst(M, II, (UnaryOperator*)Inst,
                                   (ConstPoolVal*)D);
  } else if (Inst->isTerminator()) {
    return ConstantFoldTerminator((TerminatorInst*)Inst);

  } else if (Inst->getInstType() == Instruction::PHINode) {
    PHINode *PN = (PHINode*)Inst; // If it's a PHI node and only has one operand
                                  // Then replace it directly with that operand.
    assert(PN->getOperand(0) && "PHI Node must have at least one operand!");
    if (PN->getOperand(1) == 0) {       // If the PHI Node has exactly 1 operand
      Value *V = PN->getOperand(0);
      PN->replaceAllUsesWith(V);                 // Replace all uses of this PHI
                                                 // Unlink from basic block
      PN->getParent()->getInstList().remove(II.getInstructionIterator());
      if (PN->hasName()) V->setName(PN->getName()); // Inherit PHINode name
      delete PN;                                 // Finally, delete the node...
      return true;
    }
  }
  return false;
}

// DoConstPropPass - Propogate constants and do constant folding on instructions
// this returns true if something was changed, false if nothing was changed.
//
static bool DoConstPropPass(Method *M) {
  bool SomethingChanged = false;

#if 1
  Method::inst_iterator It = M->inst_begin();
  while (It != M->inst_end())
    if (ConstantFoldInstruction(M, It)) {
      SomethingChanged = true;  // If returned true, iter is already incremented

      // Incrementing the iterator in an unchecked manner could mess up the
      // internals of 'It'.  To make sure everything is happy, tell it we might
      // have broken it.
      It.resyncInstructionIterator();
    } else {
      ++It;
    }
#else
  Method::BasicBlocksType::iterator BBIt = M->getBasicBlocks().begin();
  for (; BBIt != M->getBasicBlocks().end(); BBIt++) {
    BasicBlock *BB = *BBIt;

    BasicBlock::InstListType::iterator DI = BB->getInstList().begin();
    for (; DI != BB->getInstList().end(); DI++)
      SomethingChanged |= ConstantFoldInstruction(M, DI);
  }
#endif
  return SomethingChanged;
}

// returns true on failure, false on success...
//
bool DoConstantPropogation(Method *M) {
  bool Modified = false;

  // Fold constants until we make no progress...
  while (DoConstPropPass(M)) Modified = true;

  // Merge identical constants last: this is important because we may have just
  // introduced constants that already exist!
  //
  Modified |= MergeConstantPoolReferences(M->getConstantPool());

  return Modified;
}
<commit_msg>* Expose DoConstantPoolMerging * Cleanups (post->pre increment, new cleaner API, etc) * Moved stuff into ConstantHandling.h<commit_after>//===- ConstantProp.cpp - Code to perform Constant Propogation ------------===//
//
// This file implements constant propogation and merging:
//
// Specifically, this:
//   * Folds multiple identical constants in the constant pool together
//     Note that if one is named and the other is not, that the result gets the
//     original name.
//   * Converts instructions like "add int %1, %2" into a direct def of %3 in
//     the constant pool
//   * Converts conditional branches on a constant boolean value into direct
//     branches.
//   * Converts phi nodes with one incoming def to the incoming def directly
//   . Converts switch statements with one entry into a test & conditional
//     branch
//   . Converts switches on constant values into an unconditional branch.
//
// Notice that:
//   * This pass has a habit of making definitions be dead.  It is a good idea
//     to to run a DCE pass sometime after running this pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/Method.h"
#include "llvm/BasicBlock.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/ConstantPool.h"
#include "llvm/Opt/AllOpts.h"
#include "llvm/Opt/ConstantHandling.h"

// Merge identical constant values in the constant pool.
//
// TODO: We can do better than this simplistic N^2 algorithm...
//
bool DoConstantPoolMerging(Method *M) {
  return DoConstantPoolMerging(M->getConstantPool());
}

bool DoConstantPoolMerging(ConstantPool &CP) {
  bool Modified = false;
  for (ConstantPool::plane_iterator PI = CP.begin(); PI != CP.end(); ++PI) {
    for (ConstantPool::PlaneType::iterator I = (*PI)->begin();
	 I != (*PI)->end(); ++I) {
      ConstPoolVal *C = *I;

      ConstantPool::PlaneType::iterator J = I;
      for (++J; J != (*PI)->end(); ++J) {
	if (C->equals(*J)) {
	  Modified = true;
	  // Okay we know that *I == *J.  So now we need to make all uses of *I
	  // point to *J.
	  //
	  C->replaceAllUsesWith(*J);

	  (*PI)->remove(I); // Remove C from constant pool...

	  if (C->hasName() && !(*J)->hasName())  // The merged constant inherits
	    (*J)->setName(C->getName());         // the old name...

	  delete C;                              // Delete the constant itself.
	  break;  // Break out of inner for loop
	}
      }
    }
  }
  return Modified;
}

inline static bool
ConstantFoldUnaryInst(Method *M, Method::inst_iterator &DI,
                      UnaryOperator *Op, ConstPoolVal *D) {
  ConstPoolVal *ReplaceWith =
    ConstantFoldUnaryInstruction(Op->getInstType(), D);

  if (!ReplaceWith) return false;   // Nothing new to change...

  // Add the new value to the constant pool...
  M->getConstantPool().insert(ReplaceWith);

  // Replaces all of the uses of a variable with uses of the constant.
  Op->replaceAllUsesWith(ReplaceWith);

  // Remove the operator from the list of definitions...
  Op->getParent()->getInstList().remove(DI.getInstructionIterator());

  // The new constant inherits the old name of the operator...
  if (Op->hasName()) ReplaceWith->setName(Op->getName());

  // Delete the operator now...
  delete Op;
  return true;
}

inline static bool
ConstantFoldBinaryInst(Method *M, Method::inst_iterator &DI,
		       BinaryOperator *Op,
		       ConstPoolVal *D1, ConstPoolVal *D2) {
  ConstPoolVal *ReplaceWith =
    ConstantFoldBinaryInstruction(Op->getInstType(), D1, D2);
  if (!ReplaceWith) return false;   // Nothing new to change...

  // Add the new value to the constant pool...
  M->getConstantPool().insert(ReplaceWith);

  // Replaces all of the uses of a variable with uses of the constant.
  Op->replaceAllUsesWith(ReplaceWith);

  // Remove the operator from the list of definitions...
  Op->getParent()->getInstList().remove(DI.getInstructionIterator());

  // The new constant inherits the old name of the operator...
  if (Op->hasName()) ReplaceWith->setName(Op->getName());

  // Delete the operator now...
  delete Op;
  return true;
}

inline static bool ConstantFoldTerminator(TerminatorInst *T) {
  // Branch - See if we are conditional jumping on constant
  if (T->getInstType() == Instruction::Br) {
    BranchInst *BI = (BranchInst*)T;
    if (!BI->isUnconditional() &&              // Are we branching on constant?
        BI->getOperand(2)->isConstant()) {
      // YES.  Change to unconditional branch...
      ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
      Value *Destination = BI->getOperand(Cond->getValue() ? 0 : 1);

      BI->setOperand(0, Destination);  // Set the unconditional destination
      BI->setOperand(1, 0);            // Clear the conditional destination
      BI->setOperand(2, 0);            // Clear the condition...
      return true;
    }
  }
  return false;
}

// ConstantFoldInstruction - If an instruction references constants, try to fold
// them together...
//
inline static bool
ConstantFoldInstruction(Method *M, Method::inst_iterator &II) {
  Instruction *Inst = *II;
  if (Inst->isBinaryOp()) {
    ConstPoolVal *D1 = Inst->getOperand(0)->castConstant();
    ConstPoolVal *D2 = Inst->getOperand(1)->castConstant();

    if (D1 && D2)
      return ConstantFoldBinaryInst(M, II, (BinaryOperator*)Inst, D1, D2);

  } else if (Inst->isUnaryOp()) {
    ConstPoolVal *D = Inst->getOperand(0)->castConstant();
    if (D) return ConstantFoldUnaryInst(M, II, (UnaryOperator*)Inst, D);
  } else if (Inst->isTerminator()) {
    return ConstantFoldTerminator((TerminatorInst*)Inst);

  } else if (Inst->isPHINode()) {
    PHINode *PN = (PHINode*)Inst; // If it's a PHI node and only has one operand
                                  // Then replace it directly with that operand.
    assert(PN->getOperand(0) && "PHI Node must have at least one operand!");
    if (PN->getOperand(1) == 0) {       // If the PHI Node has exactly 1 operand
      Value *V = PN->getOperand(0);
      PN->replaceAllUsesWith(V);                 // Replace all uses of this PHI
                                                 // Unlink from basic block
      PN->getParent()->getInstList().remove(II.getInstructionIterator());
      if (PN->hasName()) V->setName(PN->getName()); // Inherit PHINode name
      delete PN;                                 // Finally, delete the node...
      return true;
    }
  }
  return false;
}

// DoConstPropPass - Propogate constants and do constant folding on instructions
// this returns true if something was changed, false if nothing was changed.
//
static bool DoConstPropPass(Method *M) {
  bool SomethingChanged = false;

#if 1
  Method::inst_iterator It = M->inst_begin();
  while (It != M->inst_end())
    if (ConstantFoldInstruction(M, It)) {
      SomethingChanged = true;  // If returned true, iter is already incremented

      // Incrementing the iterator in an unchecked manner could mess up the
      // internals of 'It'.  To make sure everything is happy, tell it we might
      // have broken it.
      It.resyncInstructionIterator();
    } else {
      ++It;
    }
#else
  for (Method::iterator BBIt = M->begin(); BBIt != M->end(); ++BBIt) {
    BasicBlock *BB = *BBIt;

    reduce_apply_bool(BB->begin(), BB->end(),
		      bind1st(ConstantFoldInstruction, M));
  }
#endif
  return SomethingChanged;
}

// returns true on failure, false on success...
//
bool DoConstantPropogation(Method *M) {
  bool Modified = false;

  // Fold constants until we make no progress...
  while (DoConstPropPass(M)) Modified = true;

  // Merge identical constants last: this is important because we may have just
  // introduced constants that already exist!
  //
  Modified |= DoConstantPoolMerging(M->getConstantPool());

  return Modified;
}
<|endoftext|>


<commit_before>//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements Loop Rotation Pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/LoopRotation.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/LoopRotationUtils.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
using namespace llvm;

#define DEBUG_TYPE "loop-rotate"

static cl::opt<unsigned> DefaultRotationThreshold(
    "rotation-max-header-size", cl::init(16), cl::Hidden,
    cl::desc("The default maximum header size for automatic loop rotation"));

LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication)
    : EnableHeaderDuplication(EnableHeaderDuplication) {}

PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
                                      LoopStandardAnalysisResults &AR,
                                      LPMUpdater &) {
  int Threshold = EnableHeaderDuplication ? DefaultRotationThreshold : 0;
  const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
  const SimplifyQuery SQ = getBestSimplifyQuery(AR, DL);

  Optional<MemorySSAUpdater> MSSAU;
  if (AR.MSSA)
    MSSAU = MemorySSAUpdater(AR.MSSA);
  bool Changed = LoopRotation(&L, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE,
                              MSSAU.hasValue() ? MSSAU.getPointer() : nullptr,
                              SQ, false, Threshold, false);

  if (!Changed)
    return PreservedAnalyses::all();

  if (AR.MSSA && VerifyMemorySSA)
    AR.MSSA->verifyMemorySSA();

  auto PA = getLoopPassPreservedAnalyses();
  if (AR.MSSA)
    PA.preserve<MemorySSAAnalysis>();
  return PA;
}

namespace {

class LoopRotateLegacyPass : public LoopPass {
  unsigned MaxHeaderSize;

public:
  static char ID; // Pass ID, replacement for typeid
  LoopRotateLegacyPass(int SpecifiedMaxHeaderSize = -1) : LoopPass(ID) {
    initializeLoopRotateLegacyPassPass(*PassRegistry::getPassRegistry());
    if (SpecifiedMaxHeaderSize == -1)
      MaxHeaderSize = DefaultRotationThreshold;
    else
      MaxHeaderSize = unsigned(SpecifiedMaxHeaderSize);
  }

  // LCSSA form makes instruction renaming easier.
  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
    if (EnableMSSALoopDependency) {
      AU.addRequired<MemorySSAWrapperPass>();
      AU.addPreserved<MemorySSAWrapperPass>();
    }
    getLoopAnalysisUsage(AU);
  }

  bool runOnLoop(Loop *L, LPPassManager &LPM) override {
    if (skipLoop(L))
      return false;
    Function &F = *L->getHeader()->getParent();

    auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
    const auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
    auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
    auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
    auto *DT = DTWP ? &DTWP->getDomTree() : nullptr;
    auto *SEWP = getAnalysisIfAvailable<ScalarEvolutionWrapperPass>();
    auto *SE = SEWP ? &SEWP->getSE() : nullptr;
    const SimplifyQuery SQ = getBestSimplifyQuery(*this, F);
    Optional<MemorySSAUpdater> MSSAU;
    if (EnableMSSALoopDependency) {
      MemorySSA *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
      MSSAU = MemorySSAUpdater(MSSA);
    }
    return LoopRotation(L, LI, TTI, AC, DT, SE,
                        MSSAU.hasValue() ? MSSAU.getPointer() : nullptr, SQ,
                        false, MaxHeaderSize, false);
  }
};
}

char LoopRotateLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
INITIALIZE_PASS_END(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops", false,
                    false)

Pass *llvm::createLoopRotatePass(int MaxHeaderSize) {
  return new LoopRotateLegacyPass(MaxHeaderSize);
}
<commit_msg>[LoopRotate] Unconditionally get ScalarEvolution.<commit_after>//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements Loop Rotation Pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/LoopRotation.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LoopPassManager.h"
#include "llvm/Transforms/Utils/LoopRotationUtils.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
using namespace llvm;

#define DEBUG_TYPE "loop-rotate"

static cl::opt<unsigned> DefaultRotationThreshold(
    "rotation-max-header-size", cl::init(16), cl::Hidden,
    cl::desc("The default maximum header size for automatic loop rotation"));

LoopRotatePass::LoopRotatePass(bool EnableHeaderDuplication)
    : EnableHeaderDuplication(EnableHeaderDuplication) {}

PreservedAnalyses LoopRotatePass::run(Loop &L, LoopAnalysisManager &AM,
                                      LoopStandardAnalysisResults &AR,
                                      LPMUpdater &) {
  int Threshold = EnableHeaderDuplication ? DefaultRotationThreshold : 0;
  const DataLayout &DL = L.getHeader()->getModule()->getDataLayout();
  const SimplifyQuery SQ = getBestSimplifyQuery(AR, DL);

  Optional<MemorySSAUpdater> MSSAU;
  if (AR.MSSA)
    MSSAU = MemorySSAUpdater(AR.MSSA);
  bool Changed = LoopRotation(&L, &AR.LI, &AR.TTI, &AR.AC, &AR.DT, &AR.SE,
                              MSSAU.hasValue() ? MSSAU.getPointer() : nullptr,
                              SQ, false, Threshold, false);

  if (!Changed)
    return PreservedAnalyses::all();

  if (AR.MSSA && VerifyMemorySSA)
    AR.MSSA->verifyMemorySSA();

  auto PA = getLoopPassPreservedAnalyses();
  if (AR.MSSA)
    PA.preserve<MemorySSAAnalysis>();
  return PA;
}

namespace {

class LoopRotateLegacyPass : public LoopPass {
  unsigned MaxHeaderSize;

public:
  static char ID; // Pass ID, replacement for typeid
  LoopRotateLegacyPass(int SpecifiedMaxHeaderSize = -1) : LoopPass(ID) {
    initializeLoopRotateLegacyPassPass(*PassRegistry::getPassRegistry());
    if (SpecifiedMaxHeaderSize == -1)
      MaxHeaderSize = DefaultRotationThreshold;
    else
      MaxHeaderSize = unsigned(SpecifiedMaxHeaderSize);
  }

  // LCSSA form makes instruction renaming easier.
  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
    if (EnableMSSALoopDependency) {
      AU.addRequired<MemorySSAWrapperPass>();
      AU.addPreserved<MemorySSAWrapperPass>();
    }
    getLoopAnalysisUsage(AU);
  }

  bool runOnLoop(Loop *L, LPPassManager &LPM) override {
    if (skipLoop(L))
      return false;
    Function &F = *L->getHeader()->getParent();

    auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
    const auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
    auto *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
    auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
    auto *DT = DTWP ? &DTWP->getDomTree() : nullptr;
    auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
    const SimplifyQuery SQ = getBestSimplifyQuery(*this, F);
    Optional<MemorySSAUpdater> MSSAU;
    if (EnableMSSALoopDependency) {
      MemorySSA *MSSA = &getAnalysis<MemorySSAWrapperPass>().getMSSA();
      MSSAU = MemorySSAUpdater(MSSA);
    }
    return LoopRotation(L, LI, TTI, AC, DT, &SE,
                        MSSAU.hasValue() ? MSSAU.getPointer() : nullptr, SQ,
                        false, MaxHeaderSize, false);
  }
};
}

char LoopRotateLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops",
                      false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_DEPENDENCY(LoopPass)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
INITIALIZE_PASS_END(LoopRotateLegacyPass, "loop-rotate", "Rotate Loops", false,
                    false)

Pass *llvm::createLoopRotatePass(int MaxHeaderSize) {
  return new LoopRotateLegacyPass(MaxHeaderSize);
}
<|endoftext|>