<commit_before>#include <iostream>
#include <string>
#include <fstream>
#include <array>
#include <utility>
#include <map>
#include <vector>
#include <algorithm>
#include <sstream>
#include <queue>
#include "IndexHelper.hpp"

using namespace std;

const array<pair<int, string>, 3> INDEXWEIGHTS {{
	{16, "titleindex"},
	{4, "webindex"},
	{1, "pageindex"}
}};

string getQueryString()
{
	ifstream input("query.txt");
	string query;
	getline(input, query);

	return query;
}

map<string, int> getWeightedResults(const string& query)
{
	map<string, int> results;
	IndexHelper helper;

	// Add the base score from the index
	for (const auto index : INDEXWEIGHTS) {
		for (auto link : helper.getLinksFromIndex(query, index.second)) {
			results[link] += index.first;
		}
	}

	for (auto& entry : results) {
		entry.second += helper.getLinksToURL(entry.first);
	}

	return results;
}

vector<string> getResults(const string& query)
{
	stringstream tokens(query);
	queue<map<string, int>> totalResults;
	string token;
	while (tokens >> token) {
		if (token.empty()) {
			continue;
		}

		totalResults.push(getWeightedResults(token));
	}
	if (totalResults.empty()) {
		return {};
	}

	// Get the first keyword results
	auto weightedResults = totalResults.front();
	totalResults.pop();

	while (!totalResults.empty()) {
		auto newResults = totalResults.front();
		totalResults.pop();
		// Merge additional keyword results into them.
		auto currentIt = weightedResults.begin();
		auto newIt = newResults.begin();
		while (currentIt != weightedResults.end() && newIt != newResults.end()) {
			if (currentIt->first == newIt->first) {
				currentIt->second += newIt->second;
				currentIt++;
				newIt++;
			} else if (currentIt->first > newIt->first) {
				newIt++;
			} else {
				weightedResults.erase(currentIt++);
			}
		}
		weightedResults.erase(currentIt, weightedResults.end());
	}

	vector<pair<int, string>> orderedResults;
	for (auto entry : weightedResults) {
		orderedResults.emplace_back(entry.second, entry.first);
	}

	sort(orderedResults.begin(), orderedResults.end(), greater<pair<int, string>>());

	vector<string> results;
	for (auto result : orderedResults) {
		results.emplace_back(result.second);
	}

	return results;

}

int main()
{
	string query = getQueryString();
	for (auto result : getResults(query)) {
		cout << result << endl;
	}
	return 0;
}
<commit_msg>Update multi-keyword search.<commit_after>#include <iostream>
#include <string>
#include <fstream>
#include <array>
#include <utility>
#include <map>
#include <vector>
#include <algorithm>
#include <sstream>
#include <queue>
#include "IndexHelper.hpp"

using namespace std;

const array<pair<int, string>, 3> INDEXWEIGHTS {{
	{16, "titleindex"},
	{4, "webindex"},
	{1, "pageindex"}
}};

string getQueryString()
{
	ifstream input("query.txt");
	string query;
	getline(input, query);

	return query;
}

map<string, int> getWeightedResults(const string& query)
{
	map<string, int> results;
	IndexHelper helper;

	// Add the base score from the index
	for (const auto index : INDEXWEIGHTS) {
		for (auto link : helper.getLinksFromIndex(query, index.second)) {
			results[link] += index.first;
		}
	}

	return results;
}

vector<string> getResults(const string& query)
{
	IndexHelper helper;
	stringstream tokens(query);
	queue<map<string, int>> totalResults;
	string token;
	while (tokens >> token) {
		if (token.empty()) {
			continue;
		}

		totalResults.push(getWeightedResults(token));
	}
	if (totalResults.empty()) {
		return {};
	}

	// Get the first keyword results
	auto weightedResults = totalResults.front();
	totalResults.pop();

	while (!totalResults.empty()) {
		auto newResults = totalResults.front();
		totalResults.pop();
		// Merge additional keyword results into them.
		auto currentIt = weightedResults.begin();
		auto newIt = newResults.begin();
		while (currentIt != weightedResults.end() && newIt != newResults.end()) {
			if (currentIt->first == newIt->first) {
				currentIt->second += newIt->second;
				currentIt++;
				newIt++;
			} else if (currentIt->first > newIt->first) {
				newIt++;
			} else {
				weightedResults.erase(currentIt++);
			}
		}
		weightedResults.erase(currentIt, weightedResults.end());
	}

	for (auto& entry : weightedResults) {
		entry.second += helper.getLinksToURL(entry.first);
	}

	vector<pair<int, string>> orderedResults;
	for (auto entry : weightedResults) {
		orderedResults.emplace_back(entry.second, entry.first);
	}

	sort(orderedResults.begin(), orderedResults.end(), greater<pair<int, string>>());

	vector<string> results;
	for (auto result : orderedResults) {
		results.emplace_back(result.second);
	}

	return results;

}

int main()
{
	string query = getQueryString();
	for (auto result : getResults(query)) {
		cout << result << endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2013 The Communi Project
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircmessagebuilder_p.h"
#include "ircmessage.h"
#include "irc.h"

IRC_BEGIN_NAMESPACE

#ifndef IRC_DOXYGEN
IrcMessageBuilder::IrcMessageBuilder(IrcConnection* connection)
{
    d.connection = connection;
    d.message = 0;
}

void IrcMessageBuilder::processMessage(IrcNumericMessage* message)
{
    switch (message->code()) {
    case Irc::RPL_MOTDSTART:
        d.message = new IrcMotdMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setParameters(QStringList(message->parameters().value(0)));
        break;
    case Irc::RPL_MOTD:
        d.message->setParameters(d.message->parameters() << message->parameters().value(1));
        break;
    case Irc::RPL_ENDOFMOTD:
        d.message->setTimeStamp(message->timeStamp());
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_NAMREPLY: {
        if (!d.message)
            d.message = new IrcNamesMessage(d.connection);
        d.message->setPrefix(message->prefix());
        int count = message->parameters().count();
        QString channel = message->parameters().value(count - 2);
        QStringList names = d.message->parameters().mid(1);
        names += message->parameters().value(count - 1).split(QLatin1Char(' '), QString::SkipEmptyParts);
        d.message->setParameters(QStringList() << channel << names);
        break;
    }
    case Irc::RPL_ENDOFNAMES:
        d.message->setTimeStamp(message->timeStamp());
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_TOPIC:
    case Irc::RPL_NOTOPIC:
        d.message = new IrcTopicMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setTimeStamp(message->timeStamp());
        d.message->setCommand(QString::number(message->code()));
        d.message->setParameters(QStringList() << message->parameters().value(1) << message->parameters().value(2));
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_CHANNELMODEIS:
        d.message = new IrcModeMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setTimeStamp(message->timeStamp());
        d.message->setCommand(QString::number(message->code()));
        d.message->setParameters(QStringList() << message->parameters().value(1) << message->parameters().value(2));
        emit messageReceived(d.message);
        d.message = 0;
        break;
    }
}
#endif // IRC_DOXYGEN

#include "moc_ircmessagebuilder_p.cpp"

IRC_END_NAMESPACE
<commit_msg>Fix IrcMessageBuilder(RPL_CHANNELMODEIS) for multiple mode args<commit_after>/*
* Copyright (C) 2008-2013 The Communi Project
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include "ircmessagebuilder_p.h"
#include "ircmessage.h"
#include "irc.h"

IRC_BEGIN_NAMESPACE

#ifndef IRC_DOXYGEN
IrcMessageBuilder::IrcMessageBuilder(IrcConnection* connection)
{
    d.connection = connection;
    d.message = 0;
}

void IrcMessageBuilder::processMessage(IrcNumericMessage* message)
{
    switch (message->code()) {
    case Irc::RPL_MOTDSTART:
        d.message = new IrcMotdMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setParameters(QStringList(message->parameters().value(0)));
        break;
    case Irc::RPL_MOTD:
        d.message->setParameters(d.message->parameters() << message->parameters().value(1));
        break;
    case Irc::RPL_ENDOFMOTD:
        d.message->setTimeStamp(message->timeStamp());
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_NAMREPLY: {
        if (!d.message)
            d.message = new IrcNamesMessage(d.connection);
        d.message->setPrefix(message->prefix());
        int count = message->parameters().count();
        QString channel = message->parameters().value(count - 2);
        QStringList names = d.message->parameters().mid(1);
        names += message->parameters().value(count - 1).split(QLatin1Char(' '), QString::SkipEmptyParts);
        d.message->setParameters(QStringList() << channel << names);
        break;
    }
    case Irc::RPL_ENDOFNAMES:
        d.message->setTimeStamp(message->timeStamp());
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_TOPIC:
    case Irc::RPL_NOTOPIC:
        d.message = new IrcTopicMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setTimeStamp(message->timeStamp());
        d.message->setCommand(QString::number(message->code()));
        d.message->setParameters(QStringList() << message->parameters().value(1) << message->parameters().value(2));
        emit messageReceived(d.message);
        d.message = 0;
        break;

    case Irc::RPL_CHANNELMODEIS:
        d.message = new IrcModeMessage(d.connection);
        d.message->setPrefix(message->prefix());
        d.message->setTimeStamp(message->timeStamp());
        d.message->setCommand(QString::number(message->code()));
        d.message->setParameters(message->parameters().mid(1));
        emit messageReceived(d.message);
        d.message = 0;
        break;
    }
}
#endif // IRC_DOXYGEN

#include "moc_ircmessagebuilder_p.cpp"

IRC_END_NAMESPACE
<|endoftext|>


<commit_before>#include "CPlayerMovementController.h"

#include "game/CGameObject.h"
#include "input\IInputProvider.h"
#include "util/Global.h"

#include "glfw/glfw3.h"

#include <glm/ext.hpp>

CPlayerMovementController::CPlayerMovementController(IInputProvider* inputProvider, float speedSide)
	:
	m_inputProvider(inputProvider),
	m_speedSide(speedSide)
{
	return;
}

CPlayerMovementController::~CPlayerMovementController()
{
	return;
}

void CPlayerMovementController::attach(CGameObject* object)
{
	m_object = object;
}

void CPlayerMovementController::detach()
{
	m_object = nullptr;
	m_rotationDegree = 0.f;
}

void CPlayerMovementController::setActive(bool state)
{
	m_active = state;
}

void CPlayerMovementController::update(float dtime)
{

	//Moving forward
	float m_forward = dtime * 40.f;
	m_object->setPosition(glm::vec3(m_object->getPosition().x, m_object->getPosition().y, m_object->getPosition().z + m_forward));

	if (m_active && m_object != nullptr)
	{
		// Rotation speed by deg / sec
		float rateOfRotation = 200.f;
		// Back rotation rate when no keys are pressed
		float backRotation = 500.f;

		// Y axis boundary for movement
		float minY = 5.f;
		float maxY = 20.f;

		glm::vec3 pos = m_object->getPosition();

		// Movement vector
		glm::vec3 dPos(0.f);

		// Move up
		if (m_inputProvider->isKeyPressed(GLFW_KEY_W))
		{
			// Y new position
			dPos.y = dtime * m_speedSide;
			if (dPos.y + pos.y > maxY)
			{
				// Move to limit
				dPos.y = maxY - pos.y;
			}
		}

		// Move down
		if (m_inputProvider->isKeyPressed(GLFW_KEY_S))
		{
			// Y new position
			dPos.y = -dtime * m_speedSide;
			if (dPos.y + pos.y < minY)
			{
				// Move to limit
				dPos.y = minY - pos.y;
			}
		}

		// Rotate left
		if (m_inputProvider->isKeyPressed(GLFW_KEY_D))
		{

			m_rotationDegree += dtime * rateOfRotation;
			if (m_rotationDegree > 90.f)
			{

				m_rotationDegree = 90.f;
			}
		}
		else if (m_rotationDegree > 0.f)
		{
			m_rotationDegree -= dtime * backRotation;
			if (m_rotationDegree < 0.f)
			{
				m_rotationDegree = 0.f;
			}
		}

		// Rotate right
		if (m_inputProvider->isKeyPressed(GLFW_KEY_A))
		{
			m_rotationDegree -= dtime * rateOfRotation;
			if (m_rotationDegree < -90.f)
			{
				m_rotationDegree = -90.f;
			}
		}
		else if (m_rotationDegree < 0.f)
		{
			m_rotationDegree += dtime * backRotation;
			if (m_rotationDegree > 0.f)
			{
				m_rotationDegree = 0.f;
			}
		}

		// Movement speed based on angle
		float dx = -m_rotationDegree * m_speedSide;

		if (dx < 0.f)
		{
			dPos.x = -std::sqrt(-dx) * dtime;
		}
		else if (dx > 0.f)
		{
			dPos.x = std::sqrt(dx) * dtime;
		}

		float rotationRad = m_rotationDegree * glm::pi<float>() / 180.f;

		// Update rotation
		m_object->setRotation(glm::vec3(m_object->getRotation().x, -rotationRad, m_object->getRotation().z));
		/*m_object->setRotation(glm::vec3(0.f, 0.f, rotationRad));*/

		// Update translation
		m_object->setPosition(m_object->getPosition() + dPos);
	}
}

void CPlayerMovementController::receiveMessage(Message msg)
{

}<commit_msg>90 degree turn<commit_after>#include "CPlayerMovementController.h"

#include "game/CGameObject.h"
#include "input/IInputProvider.h"
#include "util/Global.h"

#include "glfw/glfw3.h"

#include <glm/ext.hpp>

CPlayerMovementController::CPlayerMovementController(IInputProvider* inputProvider, float speedSide)
	:
	m_inputProvider(inputProvider),
	m_speedSide(speedSide)
{
	return;
}

CPlayerMovementController::~CPlayerMovementController()
{
	return;
}

void CPlayerMovementController::attach(CGameObject* object)
{
	m_object = object;
}

void CPlayerMovementController::detach()
{
	m_object = nullptr;
	m_rotationDegree = 0.f;
}

void CPlayerMovementController::setActive(bool state)
{
	m_active = state;
}

void CPlayerMovementController::update(float dtime)
{

	//Moving forward
	float m_forward = dtime * 40.f;
	m_object->setPosition(glm::vec3(m_object->getPosition().x, m_object->getPosition().y, m_object->getPosition().z + m_forward));

	if (m_active && m_object != nullptr)
	{
		// Rotation speed by deg / sec
		float rateOfRotation = 200.f;
		// Back rotation rate when no keys are pressed
		float backRotation = 500.f;

		// Y axis boundary for movement
		float minY = 5.f;
		float maxY = 20.f;

		glm::vec3 pos = m_object->getPosition();

		// Movement vector
		glm::vec3 dPos(0.f);

		// Move up
		if (m_inputProvider->isKeyPressed(GLFW_KEY_W))
		{
			// Y new position
			dPos.y = dtime * m_speedSide;
			if (dPos.y + pos.y > maxY)
			{
				// Move to limit
				dPos.y = maxY - pos.y;
			}
		}

		// Move down
		if (m_inputProvider->isKeyPressed(GLFW_KEY_S))
		{

			// Y new position
			dPos.y = -dtime * m_speedSide;
			if (dPos.y + pos.y < minY)
			{
				// Move to limit
				dPos.y = minY - pos.y;
			}
		}

		// Rotate left
		if (m_inputProvider->isKeyPressed(GLFW_KEY_D))
		{
			m_object->setPosition(glm::vec3(m_object->getPosition().x - m_forward, m_object->getPosition().y, m_object->getPosition().z - m_forward));
			m_rotationDegree += dtime * rateOfRotation;
			if (m_rotationDegree > 90.f)
			{

				m_rotationDegree = 90.f;
			}
		}
		else if (m_rotationDegree > 0.f)
		{
			m_rotationDegree -= dtime * backRotation;
			if (m_rotationDegree < 0.f)
			{
				m_rotationDegree = 0.f;
			}
		}

		// Rotate right
		if (m_inputProvider->isKeyPressed(GLFW_KEY_A))
		{
			m_object->setPosition(glm::vec3(m_object->getPosition().x + m_forward, m_object->getPosition().y, m_object->getPosition().z - m_forward));
			m_rotationDegree -= dtime * rateOfRotation;
			if (m_rotationDegree < -90.f)
			{
				m_rotationDegree = -90.f;
			}
		}
		else if (m_rotationDegree < 0.f)
		{
			m_rotationDegree += dtime * backRotation;
			if (m_rotationDegree > 0.f)
			{
				m_rotationDegree = 0.f;
			}
		}

		// Movement speed based on angle
		float dx = -m_rotationDegree * m_speedSide;

		if (dx < 0.f)
		{
			dPos.x = -std::sqrt(-dx) * dtime;
		}
		else if (dx > 0.f)
		{
			dPos.x = std::sqrt(dx) * dtime;
		}

		float rotationRad = m_rotationDegree * glm::pi<float>() / 180.f;

		// Update rotation
		m_object->setRotation(glm::vec3(m_object->getRotation().x, -rotationRad, m_object->getRotation().z));

		/*m_object->setRotation(glm::vec3(0.f, 0.f, rotationRad));*/

		// Update translation
		m_object->setPosition(m_object->getPosition() + dPos);
	}
}

void CPlayerMovementController::receiveMessage(Message msg)
{

}<|endoftext|>


<commit_before>/**
 * File    : G.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-12-24 20:39:21
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int T;
int H, W;
bool used[50][50];
typedef tuple<int, int> P;
map<P, P> M;
set<P> S;

void solve_subtask()
{
  int r, c;
  while (cin >> r >> c && r >= 0 && c >= 0)
  {
    cout << H - r - 1 << " " << W - c - 1 << endl;
  }
}

void solve_normal()
{
  fill(&used[0][0], &used[0][0] + 50 * 50, false);
  M.clear();
  S.clear();
  if (H * W % 2 == 0)
  {
    cout << "Second" << endl;
  }
  else
  {
    cout << "First" << endl;
    cout << 0 << " " << 0 << endl;
    used[0][0] = true;
  }
  if (H % 2 == 1)
  {
    for (auto j = 0; j < W; j++)
    {
      for (auto i = 0; i < H; i++)
      {
        if (i % 2 != j % 2)
        {
          M[P(i, j)] = P(i + 1, j);
          M[P(i + 1, j)] = P(i, j);
          used[i][j] = true;
          used[i + 1][j] = true;
        }
      }
    }
  }
  else
  {
    for (auto i = 0; i < H; i++)
    {
      for (auto j = 0; j < W; j++)
      {
        if (i % 2 != j % 2)
        {
          M[P(i, j)] = P(i, j + 1);
          M[P(i, j + 1)] = P(i, j);
          used[i][j] = true;
          used[i][j + 1] = true;
        }
      }
    }
  }
  for (auto i = 0; i < H; i++)
  {
    for (auto j = 0; j < W; j++)
    {
      if (!used[i][j])
      {
        S.insert(P(i, j));
      }
    }
  }
  int r, c;
  while (cin >> r >> c && r >= 0 && c >= 0)
  {
    used[r][c] = true;
    P p = P(r, c);
    if (M.find(p) == M.end())
    {
      S.erase(S.find(p));
      auto q = S.begin();
      int x = get<0>(*q);
      int y = get<1>(*q);
      cout << x << " " << y << endl;
      used[x][y] = true;
      S.erase(q);
    }
    else
    {
      P q = M[p];
      int x = get<0>(q);
      int y = get<1>(q);
      cout << x << " " << y << endl;
      used[x][y] = true;
    }
  }
}

void solve()
{
  cin >> H >> W;
  if (H % 2 == 0 && W % 2 == 0)
  {
    cout << "Second" << endl;
  }
  else
  {
    solve_normal();
  }
  solve_subtask();
}

int main()
{
  cin >> T;
  for (auto i = 0; i < T; i++)
  {
    solve();
  }
}<commit_msg>submit G.cpp to 'G - Good Game' (xmascon18) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : G.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-12-24 20:39:21
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int T;
int H, W;
bool used[50][50];
typedef tuple<int, int> P;
map<P, P> M;
set<P> S;

void solve_subtask()
{
  cout << "Second" << endl;
  int r, c;
  while (cin >> r >> c && r >= 0 && c >= 0)
  {
    cout << H - r - 1 << " " << W - c - 1 << endl;
  }
}

void solve_normal()
{
  fill(&used[0][0], &used[0][0] + 50 * 50, false);
  M.clear();
  S.clear();
  if (H * W % 2 == 0)
  {
    cout << "Second" << endl;
  }
  else
  {
    cout << "First" << endl;
    cout << 0 << " " << 0 << endl;
    used[0][0] = true;
  }
  if (H % 2 == 1)
  {
    for (auto j = 0; j < W; j++)
    {
      for (auto i = 0; i < H; i++)
      {
        if (i % 2 != j % 2)
        {
          M[P(i, j)] = P(i + 1, j);
          M[P(i + 1, j)] = P(i, j);
          used[i][j] = true;
          used[i + 1][j] = true;
        }
      }
    }
  }
  else
  {
    for (auto i = 0; i < H; i++)
    {
      for (auto j = 0; j < W; j++)
      {
        if (i % 2 != j % 2)
        {
          M[P(i, j)] = P(i, j + 1);
          M[P(i, j + 1)] = P(i, j);
          used[i][j] = true;
          used[i][j + 1] = true;
        }
      }
    }
  }
  for (auto i = 0; i < H; i++)
  {
    for (auto j = 0; j < W; j++)
    {
      if (!used[i][j])
      {
        S.insert(P(i, j));
      }
    }
  }
  int r, c;
  while (cin >> r >> c && r >= 0 && c >= 0)
  {
    used[r][c] = true;
    P p = P(r, c);
    if (M.find(p) == M.end())
    {
      S.erase(S.find(p));
      auto q = S.begin();
      int x = get<0>(*q);
      int y = get<1>(*q);
      cout << x << " " << y << endl;
      used[x][y] = true;
      S.erase(q);
    }
    else
    {
      P q = M[p];
      int x = get<0>(q);
      int y = get<1>(q);
      cout << x << " " << y << endl;
      used[x][y] = true;
    }
  }
}

void solve()
{
  cin >> H >> W;
  if (H % 2 == 0 && W % 2 == 0)
  {
    solve_subtask();
  }
  else
  {
    solve_normal();
  }
}

int main()
{
  cin >> T;
  for (auto i = 0; i < T; i++)
  {
    solve();
  }
}<|endoftext|>


<commit_before>//===- PassManagerBuilder.cpp - Build Standard Pass -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PassManagerBuilder class, which is used to set up a
// "standard" optimization sequence suitable for languages like C and C++.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm-c/Transforms/PassManagerBuilder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/DefaultPasses.h"
#include "llvm/PassManager.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Vectorize.h"

using namespace llvm;

static cl::opt<bool>
RunLoopVectorization("vectorize-loops",
                     cl::desc("Run the Loop vectorization passes"));

static cl::opt<bool>
RunBBVectorization("vectorize", cl::desc("Run the BB vectorization passes"));

static cl::opt<bool>
UseGVNAfterVectorization("use-gvn-after-vectorization",
  cl::init(false), cl::Hidden,
  cl::desc("Run GVN instead of Early CSE after vectorization passes"));

static cl::opt<bool> UseNewSROA("use-new-sroa",
  cl::init(true), cl::Hidden,
  cl::desc("Enable the new, experimental SROA pass"));

PassManagerBuilder::PassManagerBuilder() {
    OptLevel = 2;
    SizeLevel = 0;
    LibraryInfo = 0;
    Inliner = 0;
    DisableSimplifyLibCalls = false;
    DisableUnitAtATime = false;
    DisableUnrollLoops = false;
    Vectorize = RunBBVectorization;
    LoopVectorize = RunLoopVectorization;
}

PassManagerBuilder::~PassManagerBuilder() {
  delete LibraryInfo;
  delete Inliner;
}

/// Set of global extensions, automatically added as part of the standard set.
static ManagedStatic<SmallVector<std::pair<PassManagerBuilder::ExtensionPointTy,
   PassManagerBuilder::ExtensionFn>, 8> > GlobalExtensions;

void PassManagerBuilder::addGlobalExtension(
    PassManagerBuilder::ExtensionPointTy Ty,
    PassManagerBuilder::ExtensionFn Fn) {
  GlobalExtensions->push_back(std::make_pair(Ty, Fn));
}

void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
  Extensions.push_back(std::make_pair(Ty, Fn));
}

void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy,
                                           PassManagerBase &PM) const {
  for (unsigned i = 0, e = GlobalExtensions->size(); i != e; ++i)
    if ((*GlobalExtensions)[i].first == ETy)
      (*GlobalExtensions)[i].second(*this, PM);
  for (unsigned i = 0, e = Extensions.size(); i != e; ++i)
    if (Extensions[i].first == ETy)
      Extensions[i].second(*this, PM);
}

void
PassManagerBuilder::addInitialAliasAnalysisPasses(PassManagerBase &PM) const {
  // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
  // BasicAliasAnalysis wins if they disagree. This is intended to help
  // support "obvious" type-punning idioms.
  PM.add(createTypeBasedAliasAnalysisPass());
  PM.add(createBasicAliasAnalysisPass());
}

void PassManagerBuilder::populateFunctionPassManager(FunctionPassManager &FPM) {
  addExtensionsToPM(EP_EarlyAsPossible, FPM);

  // Add LibraryInfo if we have some.
  if (LibraryInfo) FPM.add(new TargetLibraryInfo(*LibraryInfo));

  if (OptLevel == 0) return;

  addInitialAliasAnalysisPasses(FPM);

  FPM.add(createCFGSimplificationPass());
  if (UseNewSROA)
    FPM.add(createSROAPass());
  else
    FPM.add(createScalarReplAggregatesPass());
  FPM.add(createEarlyCSEPass());
  FPM.add(createLowerExpectIntrinsicPass());
}

void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
  // If all optimizations are disabled, just run the always-inline pass.
  if (OptLevel == 0) {
    if (Inliner) {
      MPM.add(Inliner);
      Inliner = 0;
    }

    // FIXME: This is a HACK! The inliner pass above implicitly creates a CGSCC
    // pass manager, but we don't want to add extensions into that pass manager.
    // To prevent this we must insert a no-op module pass to reset the pass
    // manager to get the same behavior as EP_OptimizerLast in non-O0 builds.
    if (!GlobalExtensions->empty() || !Extensions.empty())
      MPM.add(createBarrierNoopPass());

    addExtensionsToPM(EP_EnabledOnOptLevel0, MPM);
    return;
  }

  // Add LibraryInfo if we have some.
  if (LibraryInfo) MPM.add(new TargetLibraryInfo(*LibraryInfo));

  addInitialAliasAnalysisPasses(MPM);

  if (!DisableUnitAtATime) {
    addExtensionsToPM(EP_ModuleOptimizerEarly, MPM);

    MPM.add(createGlobalOptimizerPass());     // Optimize out global vars

    MPM.add(createIPSCCPPass());              // IP SCCP
    MPM.add(createDeadArgEliminationPass());  // Dead argument elimination

    MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE
    MPM.add(createCFGSimplificationPass());   // Clean up after IPCP & DAE
  }

  // Start of CallGraph SCC passes.
  if (!DisableUnitAtATime)
    MPM.add(createPruneEHPass());             // Remove dead EH info
  if (Inliner) {
    MPM.add(Inliner);
    Inliner = 0;
  }
  if (!DisableUnitAtATime)
    MPM.add(createFunctionAttrsPass());       // Set readonly/readnone attrs
  if (OptLevel > 2)
    MPM.add(createArgumentPromotionPass());   // Scalarize uninlined fn args

  // Start of function pass.
  // Break up aggregate allocas, using SSAUpdater.
  if (UseNewSROA)
    MPM.add(createSROAPass(/*RequiresDomTree*/ false));
  else
    MPM.add(createScalarReplAggregatesPass(-1, false));
  MPM.add(createEarlyCSEPass());              // Catch trivial redundancies
  if (!DisableSimplifyLibCalls)
    MPM.add(createSimplifyLibCallsPass());    // Library Call Optimizations
  MPM.add(createJumpThreadingPass());         // Thread jumps.
  MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createInstructionCombiningPass());  // Combine silly seq's

  MPM.add(createTailCallEliminationPass());   // Eliminate tail calls
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createReassociatePass());           // Reassociate expressions
  MPM.add(createLoopRotatePass());            // Rotate Loop
  MPM.add(createLICMPass());                  // Hoist loop invariants
  MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3));
  MPM.add(createInstructionCombiningPass());
  MPM.add(createIndVarSimplifyPass());        // Canonicalize indvars
  MPM.add(createLoopIdiomPass());             // Recognize idioms like memset.
  MPM.add(createLoopDeletionPass());          // Delete dead loops

  if (LoopVectorize && OptLevel > 1)
    MPM.add(createLoopVectorizePass());

  if (!DisableUnrollLoops)
    MPM.add(createLoopUnrollPass());          // Unroll small loops
  addExtensionsToPM(EP_LoopOptimizerEnd, MPM);

  if (OptLevel > 1)
    MPM.add(createGVNPass());                 // Remove redundancies
  MPM.add(createMemCpyOptPass());             // Remove memcpy / form memset
  MPM.add(createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  MPM.add(createInstructionCombiningPass());
  MPM.add(createJumpThreadingPass());         // Thread jumps
  MPM.add(createCorrelatedValuePropagationPass());
  MPM.add(createDeadStoreEliminationPass());  // Delete dead stores

  addExtensionsToPM(EP_ScalarOptimizerLate, MPM);

  if (Vectorize) {
    MPM.add(createBBVectorizePass());
    MPM.add(createInstructionCombiningPass());
    if (OptLevel > 1 && UseGVNAfterVectorization)
      MPM.add(createGVNPass());                   // Remove redundancies
    else
      MPM.add(createEarlyCSEPass());              // Catch trivial redundancies
  }

  MPM.add(createAggressiveDCEPass());         // Delete dead instructions
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createInstructionCombiningPass());  // Clean up after everything.

  if (!DisableUnitAtATime) {
    // FIXME: We shouldn't bother with this anymore.
    MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes

    // GlobalOpt already deletes dead functions and globals, at -O2 try a
    // late pass of GlobalDCE.  It is capable of deleting dead cycles.
    if (OptLevel > 1) {
      MPM.add(createGlobalDCEPass());         // Remove dead fns and globals.
      MPM.add(createConstantMergePass());     // Merge dup global constants
    }
  }
  addExtensionsToPM(EP_OptimizerLast, MPM);
}

void PassManagerBuilder::populateLTOPassManager(PassManagerBase &PM,
                                                bool Internalize,
                                                bool RunInliner,
                                                bool DisableGVNLoadPRE) {
  // Provide AliasAnalysis services for optimizations.
  addInitialAliasAnalysisPasses(PM);

  // Now that composite has been compiled, scan through the module, looking
  // for a main function.  If main is defined, mark all other functions
  // internal.
  if (Internalize) {
    std::vector<const char*> E;
    E.push_back("main");
    PM.add(createInternalizePass(E));
  }

  // Propagate constants at call sites into the functions they call.  This
  // opens opportunities for globalopt (and inlining) by substituting function
  // pointers passed as arguments to direct uses of functions.
  PM.add(createIPSCCPPass());

  // Now that we internalized some globals, see if we can hack on them!
  PM.add(createGlobalOptimizerPass());

  // Linking modules together can lead to duplicated global constants, only
  // keep one copy of each constant.
  PM.add(createConstantMergePass());

  // Remove unused arguments from functions.
  PM.add(createDeadArgEliminationPass());

  // Reduce the code after globalopt and ipsccp.  Both can open up significant
  // simplification opportunities, and both can propagate functions through
  // function pointers.  When this happens, we often have to resolve varargs
  // calls, etc, so let instcombine do this.
  PM.add(createInstructionCombiningPass());

  // Inline small functions
  if (RunInliner)
    PM.add(createFunctionInliningPass());

  PM.add(createPruneEHPass());   // Remove dead EH info.

  // Optimize globals again if we ran the inliner.
  if (RunInliner)
    PM.add(createGlobalOptimizerPass());
  PM.add(createGlobalDCEPass()); // Remove dead functions.

  // If we didn't decide to inline a function, check to see if we can
  // transform it to pass arguments by value instead of by reference.
  PM.add(createArgumentPromotionPass());

  // The IPO passes may leave cruft around.  Clean up after them.
  PM.add(createInstructionCombiningPass());
  PM.add(createJumpThreadingPass());
  // Break up allocas
  if (UseNewSROA)
    PM.add(createSROAPass());
  else
    PM.add(createScalarReplAggregatesPass());

  // Run a few AA driven optimizations here and now, to cleanup the code.
  PM.add(createFunctionAttrsPass()); // Add nocapture.
  PM.add(createGlobalsModRefPass()); // IP alias analysis.

  PM.add(createLICMPass());                 // Hoist loop invariants.
  PM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies.
  PM.add(createMemCpyOptPass());            // Remove dead memcpys.
  // Nuke dead stores.
  PM.add(createDeadStoreEliminationPass());

  // Cleanup and simplify the code after the scalar optimizations.
  PM.add(createInstructionCombiningPass());

  PM.add(createJumpThreadingPass());

  // Delete basic blocks, which optimization passes may have killed.
  PM.add(createCFGSimplificationPass());

  // Now that we have optimized the program, discard unreachable functions.
  PM.add(createGlobalDCEPass());
}

LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate() {
  PassManagerBuilder *PMB = new PassManagerBuilder();
  return wrap(PMB);
}

void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
  PassManagerBuilder *Builder = unwrap(PMB);
  delete Builder;
}

void
LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB,
                                  unsigned OptLevel) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->OptLevel = OptLevel;
}

void
LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB,
                                   unsigned SizeLevel) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->SizeLevel = SizeLevel;
}

void
LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB,
                                            LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableUnitAtATime = Value;
}

void
LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB,
                                            LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableUnrollLoops = Value;
}

void
LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB,
                                                 LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableSimplifyLibCalls = Value;
}

void
LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB,
                                              unsigned Threshold) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->Inliner = createFunctionInliningPass(Threshold);
}

void
LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB,
                                                  LLVMPassManagerRef PM) {
  PassManagerBuilder *Builder = unwrap(PMB);
  FunctionPassManager *FPM = unwrap<FunctionPassManager>(PM);
  Builder->populateFunctionPassManager(*FPM);
}

void
LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB,
                                                LLVMPassManagerRef PM) {
  PassManagerBuilder *Builder = unwrap(PMB);
  PassManagerBase *MPM = unwrap(PM);
  Builder->populateModulePassManager(*MPM);
}

void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
                                                  LLVMPassManagerRef PM,
                                                  bool Internalize,
                                                  bool RunInliner) {
  PassManagerBuilder *Builder = unwrap(PMB);
  PassManagerBase *LPM = unwrap(PM);
  Builder->populateLTOPassManager(*LPM, Internalize, RunInliner);
}
<commit_msg>Enable the loop vectorizer.<commit_after>//===- PassManagerBuilder.cpp - Build Standard Pass -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PassManagerBuilder class, which is used to set up a
// "standard" optimization sequence suitable for languages like C and C++.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm-c/Transforms/PassManagerBuilder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/DefaultPasses.h"
#include "llvm/PassManager.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Vectorize.h"

using namespace llvm;

static cl::opt<bool>
RunLoopVectorization("vectorize-loops",
                     cl::desc("Run the Loop vectorization passes"));

static cl::opt<bool>
RunBBVectorization("vectorize", cl::desc("Run the BB vectorization passes"));

static cl::opt<bool>
UseGVNAfterVectorization("use-gvn-after-vectorization",
  cl::init(false), cl::Hidden,
  cl::desc("Run GVN instead of Early CSE after vectorization passes"));

static cl::opt<bool> UseNewSROA("use-new-sroa",
  cl::init(true), cl::Hidden,
  cl::desc("Enable the new, experimental SROA pass"));

PassManagerBuilder::PassManagerBuilder() {
    OptLevel = 2;
    SizeLevel = 0;
    LibraryInfo = 0;
    Inliner = 0;
    DisableSimplifyLibCalls = false;
    DisableUnitAtATime = false;
    DisableUnrollLoops = false;
    Vectorize = RunBBVectorization;
    LoopVectorize = RunLoopVectorization;
}

PassManagerBuilder::~PassManagerBuilder() {
  delete LibraryInfo;
  delete Inliner;
}

/// Set of global extensions, automatically added as part of the standard set.
static ManagedStatic<SmallVector<std::pair<PassManagerBuilder::ExtensionPointTy,
   PassManagerBuilder::ExtensionFn>, 8> > GlobalExtensions;

void PassManagerBuilder::addGlobalExtension(
    PassManagerBuilder::ExtensionPointTy Ty,
    PassManagerBuilder::ExtensionFn Fn) {
  GlobalExtensions->push_back(std::make_pair(Ty, Fn));
}

void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
  Extensions.push_back(std::make_pair(Ty, Fn));
}

void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy,
                                           PassManagerBase &PM) const {
  for (unsigned i = 0, e = GlobalExtensions->size(); i != e; ++i)
    if ((*GlobalExtensions)[i].first == ETy)
      (*GlobalExtensions)[i].second(*this, PM);
  for (unsigned i = 0, e = Extensions.size(); i != e; ++i)
    if (Extensions[i].first == ETy)
      Extensions[i].second(*this, PM);
}

void
PassManagerBuilder::addInitialAliasAnalysisPasses(PassManagerBase &PM) const {
  // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
  // BasicAliasAnalysis wins if they disagree. This is intended to help
  // support "obvious" type-punning idioms.
  PM.add(createTypeBasedAliasAnalysisPass());
  PM.add(createBasicAliasAnalysisPass());
}

void PassManagerBuilder::populateFunctionPassManager(FunctionPassManager &FPM) {
  addExtensionsToPM(EP_EarlyAsPossible, FPM);

  // Add LibraryInfo if we have some.
  if (LibraryInfo) FPM.add(new TargetLibraryInfo(*LibraryInfo));

  if (OptLevel == 0) return;

  addInitialAliasAnalysisPasses(FPM);

  FPM.add(createCFGSimplificationPass());
  if (UseNewSROA)
    FPM.add(createSROAPass());
  else
    FPM.add(createScalarReplAggregatesPass());
  FPM.add(createEarlyCSEPass());
  FPM.add(createLowerExpectIntrinsicPass());
}

void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
  // If all optimizations are disabled, just run the always-inline pass.
  if (OptLevel == 0) {
    if (Inliner) {
      MPM.add(Inliner);
      Inliner = 0;
    }

    // FIXME: This is a HACK! The inliner pass above implicitly creates a CGSCC
    // pass manager, but we don't want to add extensions into that pass manager.
    // To prevent this we must insert a no-op module pass to reset the pass
    // manager to get the same behavior as EP_OptimizerLast in non-O0 builds.
    if (!GlobalExtensions->empty() || !Extensions.empty())
      MPM.add(createBarrierNoopPass());

    addExtensionsToPM(EP_EnabledOnOptLevel0, MPM);
    return;
  }

  // Add LibraryInfo if we have some.
  if (LibraryInfo) MPM.add(new TargetLibraryInfo(*LibraryInfo));

  addInitialAliasAnalysisPasses(MPM);

  if (!DisableUnitAtATime) {
    addExtensionsToPM(EP_ModuleOptimizerEarly, MPM);

    MPM.add(createGlobalOptimizerPass());     // Optimize out global vars

    MPM.add(createIPSCCPPass());              // IP SCCP
    MPM.add(createDeadArgEliminationPass());  // Dead argument elimination

    MPM.add(createInstructionCombiningPass());// Clean up after IPCP & DAE
    MPM.add(createCFGSimplificationPass());   // Clean up after IPCP & DAE
  }

  // Start of CallGraph SCC passes.
  if (!DisableUnitAtATime)
    MPM.add(createPruneEHPass());             // Remove dead EH info
  if (Inliner) {
    MPM.add(Inliner);
    Inliner = 0;
  }
  if (!DisableUnitAtATime)
    MPM.add(createFunctionAttrsPass());       // Set readonly/readnone attrs
  if (OptLevel > 2)
    MPM.add(createArgumentPromotionPass());   // Scalarize uninlined fn args

  // Start of function pass.
  // Break up aggregate allocas, using SSAUpdater.
  if (UseNewSROA)
    MPM.add(createSROAPass(/*RequiresDomTree*/ false));
  else
    MPM.add(createScalarReplAggregatesPass(-1, false));
  MPM.add(createEarlyCSEPass());              // Catch trivial redundancies
  if (!DisableSimplifyLibCalls)
    MPM.add(createSimplifyLibCallsPass());    // Library Call Optimizations
  MPM.add(createJumpThreadingPass());         // Thread jumps.
  MPM.add(createCorrelatedValuePropagationPass()); // Propagate conditionals
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createInstructionCombiningPass());  // Combine silly seq's

  MPM.add(createTailCallEliminationPass());   // Eliminate tail calls
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createReassociatePass());           // Reassociate expressions
  MPM.add(createLoopRotatePass());            // Rotate Loop
  MPM.add(createLICMPass());                  // Hoist loop invariants
  MPM.add(createLoopUnswitchPass(SizeLevel || OptLevel < 3));
  MPM.add(createInstructionCombiningPass());
  MPM.add(createIndVarSimplifyPass());        // Canonicalize indvars
  MPM.add(createLoopIdiomPass());             // Recognize idioms like memset.
  MPM.add(createLoopDeletionPass());          // Delete dead loops

  if (true && OptLevel > 1)
    MPM.add(createLoopVectorizePass());

  if (!DisableUnrollLoops)
    MPM.add(createLoopUnrollPass());          // Unroll small loops
  addExtensionsToPM(EP_LoopOptimizerEnd, MPM);

  if (OptLevel > 1)
    MPM.add(createGVNPass());                 // Remove redundancies
  MPM.add(createMemCpyOptPass());             // Remove memcpy / form memset
  MPM.add(createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  MPM.add(createInstructionCombiningPass());
  MPM.add(createJumpThreadingPass());         // Thread jumps
  MPM.add(createCorrelatedValuePropagationPass());
  MPM.add(createDeadStoreEliminationPass());  // Delete dead stores

  addExtensionsToPM(EP_ScalarOptimizerLate, MPM);

  if (Vectorize) {
    MPM.add(createBBVectorizePass());
    MPM.add(createInstructionCombiningPass());
    if (OptLevel > 1 && UseGVNAfterVectorization)
      MPM.add(createGVNPass());                   // Remove redundancies
    else
      MPM.add(createEarlyCSEPass());              // Catch trivial redundancies
  }

  MPM.add(createAggressiveDCEPass());         // Delete dead instructions
  MPM.add(createCFGSimplificationPass());     // Merge & remove BBs
  MPM.add(createInstructionCombiningPass());  // Clean up after everything.

  if (!DisableUnitAtATime) {
    // FIXME: We shouldn't bother with this anymore.
    MPM.add(createStripDeadPrototypesPass()); // Get rid of dead prototypes

    // GlobalOpt already deletes dead functions and globals, at -O2 try a
    // late pass of GlobalDCE.  It is capable of deleting dead cycles.
    if (OptLevel > 1) {
      MPM.add(createGlobalDCEPass());         // Remove dead fns and globals.
      MPM.add(createConstantMergePass());     // Merge dup global constants
    }
  }
  addExtensionsToPM(EP_OptimizerLast, MPM);
}

void PassManagerBuilder::populateLTOPassManager(PassManagerBase &PM,
                                                bool Internalize,
                                                bool RunInliner,
                                                bool DisableGVNLoadPRE) {
  // Provide AliasAnalysis services for optimizations.
  addInitialAliasAnalysisPasses(PM);

  // Now that composite has been compiled, scan through the module, looking
  // for a main function.  If main is defined, mark all other functions
  // internal.
  if (Internalize) {
    std::vector<const char*> E;
    E.push_back("main");
    PM.add(createInternalizePass(E));
  }

  // Propagate constants at call sites into the functions they call.  This
  // opens opportunities for globalopt (and inlining) by substituting function
  // pointers passed as arguments to direct uses of functions.
  PM.add(createIPSCCPPass());

  // Now that we internalized some globals, see if we can hack on them!
  PM.add(createGlobalOptimizerPass());

  // Linking modules together can lead to duplicated global constants, only
  // keep one copy of each constant.
  PM.add(createConstantMergePass());

  // Remove unused arguments from functions.
  PM.add(createDeadArgEliminationPass());

  // Reduce the code after globalopt and ipsccp.  Both can open up significant
  // simplification opportunities, and both can propagate functions through
  // function pointers.  When this happens, we often have to resolve varargs
  // calls, etc, so let instcombine do this.
  PM.add(createInstructionCombiningPass());

  // Inline small functions
  if (RunInliner)
    PM.add(createFunctionInliningPass());

  PM.add(createPruneEHPass());   // Remove dead EH info.

  // Optimize globals again if we ran the inliner.
  if (RunInliner)
    PM.add(createGlobalOptimizerPass());
  PM.add(createGlobalDCEPass()); // Remove dead functions.

  // If we didn't decide to inline a function, check to see if we can
  // transform it to pass arguments by value instead of by reference.
  PM.add(createArgumentPromotionPass());

  // The IPO passes may leave cruft around.  Clean up after them.
  PM.add(createInstructionCombiningPass());
  PM.add(createJumpThreadingPass());
  // Break up allocas
  if (UseNewSROA)
    PM.add(createSROAPass());
  else
    PM.add(createScalarReplAggregatesPass());

  // Run a few AA driven optimizations here and now, to cleanup the code.
  PM.add(createFunctionAttrsPass()); // Add nocapture.
  PM.add(createGlobalsModRefPass()); // IP alias analysis.

  PM.add(createLICMPass());                 // Hoist loop invariants.
  PM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies.
  PM.add(createMemCpyOptPass());            // Remove dead memcpys.
  // Nuke dead stores.
  PM.add(createDeadStoreEliminationPass());

  // Cleanup and simplify the code after the scalar optimizations.
  PM.add(createInstructionCombiningPass());

  PM.add(createJumpThreadingPass());

  // Delete basic blocks, which optimization passes may have killed.
  PM.add(createCFGSimplificationPass());

  // Now that we have optimized the program, discard unreachable functions.
  PM.add(createGlobalDCEPass());
}

LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate() {
  PassManagerBuilder *PMB = new PassManagerBuilder();
  return wrap(PMB);
}

void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
  PassManagerBuilder *Builder = unwrap(PMB);
  delete Builder;
}

void
LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB,
                                  unsigned OptLevel) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->OptLevel = OptLevel;
}

void
LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB,
                                   unsigned SizeLevel) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->SizeLevel = SizeLevel;
}

void
LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB,
                                            LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableUnitAtATime = Value;
}

void
LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB,
                                            LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableUnrollLoops = Value;
}

void
LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB,
                                                 LLVMBool Value) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->DisableSimplifyLibCalls = Value;
}

void
LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB,
                                              unsigned Threshold) {
  PassManagerBuilder *Builder = unwrap(PMB);
  Builder->Inliner = createFunctionInliningPass(Threshold);
}

void
LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB,
                                                  LLVMPassManagerRef PM) {
  PassManagerBuilder *Builder = unwrap(PMB);
  FunctionPassManager *FPM = unwrap<FunctionPassManager>(PM);
  Builder->populateFunctionPassManager(*FPM);
}

void
LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB,
                                                LLVMPassManagerRef PM) {
  PassManagerBuilder *Builder = unwrap(PMB);
  PassManagerBase *MPM = unwrap(PM);
  Builder->populateModulePassManager(*MPM);
}

void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
                                                  LLVMPassManagerRef PM,
                                                  bool Internalize,
                                                  bool RunInliner) {
  PassManagerBuilder *Builder = unwrap(PMB);
  PassManagerBase *LPM = unwrap(PM);
  Builder->populateLTOPassManager(*LPM, Internalize, RunInliner);
}
<|endoftext|>


<commit_before>/*
   Copyright 2016 Mitchell Young

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "scattering_matrix.hpp"

#include <iomanip>
#include <iostream>

namespace mocc {
    ScatteringMatrix::ScatteringMatrix( const std::vector<VecF> &scat){

        // Imply ng_ from the size of the passed-in vectors
        ng_ = scat.size();
        out_ = VecF(ng_, 0.0);
        rows_.reserve(ng_);

        // Determine the size of scat_ and save the bounds for ScatteringRows
        int size = 0;
        std::vector<std::pair<int, int>> bounds;
        bounds.reserve(ng_);

        int to = 0;
        for( const auto &scatRow: scat ) {
            std::pair<int, int> these_bounds;
            for( int from=0; from<ng_; from++ ) {
                these_bounds.first = from;
                if( scatRow[from] > 0.0 ) {
                    break;
                }
            }
            for( int from=ng_-1; from>=0; from-- ) {
                these_bounds.second = from;
                if( scatRow[from] > 0.0 ) {
                    break;
                }
            }
            if( these_bounds.first==ng_-1 && these_bounds.second==0 ) {
                these_bounds.first = to;
                these_bounds.second = to;
            }
            size += these_bounds.second-these_bounds.first+1;
            bounds.push_back(these_bounds);

            to++;
        }

        scat_.reserve(size);

        auto *begin = scat_.data();

        to=0;
        int pos=0;
        for( auto & these_bounds: bounds ) {
            for ( int from=these_bounds.first;
                    from<=these_bounds.second; from++ ) {
                scat_.push_back(scat[to][from]);
                out_[from] += scat[to][from];
            }
            rows_.push_back(ScatteringRow(these_bounds.first,
                        these_bounds.second, &scat_[pos]));
            to++;
            pos += these_bounds.second-these_bounds.first+1;
        }

        // Check whether scat_ is reallocated
        assert( begin == scat_.data() );
    }

    ScatteringMatrix::ScatteringMatrix(const ArrayB2 &scat){
        // Make sure that scat is square
        assert(scat.extent(0) == scat.extent(1));

        // Imply ng_ from the size of the passed-in vectors
        ng_ = scat.extent(0);
        out_ = VecF(ng_, 0.0);
        rows_.reserve(ng_);

        // Determien the size of scat_ and save the bounds for ScatteringRows
        int size = 0;
        std::vector<std::pair<int, int>> bounds;
        bounds.reserve(ng_);

        for( int to=0; to<ng_; to++ ) {
            std::pair<int, int> these_bounds;
            for( int from=0; from<ng_; from++ ) {
                these_bounds.first = from;
                if( scat(to, from) > 0.0 ) {
                    break;
                }
            }
            for( int from=ng_-1; from>=0; from-- ) {
                these_bounds.second = from;
                if( scat(to, from) > 0.0 ) {
                    break;
                }
            }
            if( these_bounds.first==ng_-1 && these_bounds.second==0 ) {
                these_bounds.first = to;
                these_bounds.second = to;
            }
            size += these_bounds.second-these_bounds.first+1;
            bounds.push_back(these_bounds);
        }

        scat_.reserve(size);

        auto *begin = scat_.data();

        int to = 0;
        int pos = 0;
        for( auto & these_bounds: bounds ) {
            for ( int from=these_bounds.first;
                    from<=these_bounds.second; from++ ) {
                scat_.push_back(scat(to, from));
                out_[from] += scat(to, from);
            }
            rows_.push_back(ScatteringRow(these_bounds.first,
                        these_bounds.second, &scat_[pos]));
            to++;
            pos += these_bounds.second-these_bounds.first+1;
        }

        // Check whether scat_ is reallocated
        assert( begin == scat_.data() );
    }

    std::ostream& operator<<( std::ostream& os,
            const ScatteringMatrix &scat_mat ) {
        for( auto &row: scat_mat.rows_ ) {
            int gmin = row.min_g;
            int gmax = row.max_g;
            for( int ig=0; ig<gmin; ig++ ) {
                os << std::setw(12) << 0.0;
            }

            for( int ig=gmin; ig<=gmax; ig++ ) {
                os << std::setw(12) << row[ig];
            }

            for( int ig=gmax+1; ig<scat_mat.ng_; ig++) {
                os << std::setw(12) << 0.0;
            }
            os << std::endl;
        }
        return os;
    }
}
<commit_msg>Add comments on the special treatment of empty scattering row.<commit_after>/*
   Copyright 2016 Mitchell Young

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "scattering_matrix.hpp"

#include <iomanip>
#include <iostream>

namespace mocc {
    ScatteringMatrix::ScatteringMatrix( const std::vector<VecF> &scat){

        // Imply ng_ from the size of the passed-in vectors
        ng_ = scat.size();
        out_ = VecF(ng_, 0.0);
        rows_.reserve(ng_);

        // Determine the size of scat_ and save the bounds for ScatteringRows
        int size = 0;
        std::vector<std::pair<int, int>> bounds;
        bounds.reserve(ng_);

        int to = 0;
        for( const auto &scatRow: scat ) {
            std::pair<int, int> these_bounds;
            for( int from=0; from<ng_; from++ ) {
                these_bounds.first = from;
                if( scatRow[from] > 0.0 ) {
                    break;
                }
            }
            for( int from=ng_-1; from>=0; from-- ) {
                these_bounds.second = from;
                if( scatRow[from] > 0.0 ) {
                    break;
                }
            }
            // Handle empty scattering rows. If the min and max g end up on the
            // other side of the group range, we didn't find any non-zero cross
            // sections. Set min_g and max_g to the current group. When we pack
            // the cross sections into their dense representations, we make sure
            // to add a corresponding zero
            if( these_bounds.first==ng_-1 && these_bounds.second==0 ) {
                these_bounds.first = to;
                these_bounds.second = to;
            }
            size += these_bounds.second-these_bounds.first+1;
            bounds.push_back(these_bounds);

            to++;
        }

        scat_.reserve(size);

        auto *begin = scat_.data();

        to=0;
        int pos=0;
        for( auto & these_bounds: bounds ) {
            for ( int from=these_bounds.first;
                    from<=these_bounds.second; from++ ) {
                scat_.push_back(scat[to][from]);
                out_[from] += scat[to][from];
            }
            rows_.push_back(ScatteringRow(these_bounds.first,
                        these_bounds.second, &scat_[pos]));
            to++;
            pos += these_bounds.second-these_bounds.first+1;
        }

        // Check whether scat_ is reallocated
        assert( begin == scat_.data() );
    }

    ScatteringMatrix::ScatteringMatrix(const ArrayB2 &scat){
        // Make sure that scat is square
        assert(scat.extent(0) == scat.extent(1));

        // Imply ng_ from the size of the passed-in vectors
        ng_ = scat.extent(0);
        out_ = VecF(ng_, 0.0);
        rows_.reserve(ng_);

        // Determien the size of scat_ and save the bounds for ScatteringRows
        int size = 0;
        std::vector<std::pair<int, int>> bounds;
        bounds.reserve(ng_);

        for( int to=0; to<ng_; to++ ) {
            std::pair<int, int> these_bounds;
            for( int from=0; from<ng_; from++ ) {
                these_bounds.first = from;
                if( scat(to, from) > 0.0 ) {
                    break;
                }
            }
            for( int from=ng_-1; from>=0; from-- ) {
                these_bounds.second = from;
                if( scat(to, from) > 0.0 ) {
                    break;
                }
            }
            // Handle empty scattering rows. If the min and max g end up on the
            // other side of the group range, we didn't find any non-zero cross
            // sections. Set min_g and max_g to the current group. When we pack
            // the cross sections into their dense representations, we make sure
            // to add a corresponding zero
            if( these_bounds.first==ng_-1 && these_bounds.second==0 ) {
                these_bounds.first = to;
                these_bounds.second = to;
            }
            size += these_bounds.second-these_bounds.first+1;
            bounds.push_back(these_bounds);
        }

        scat_.reserve(size);

        auto *begin = scat_.data();

        int to = 0;
        int pos = 0;
        for( auto & these_bounds: bounds ) {
            for ( int from=these_bounds.first;
                    from<=these_bounds.second; from++ ) {
                scat_.push_back(scat(to, from));
                out_[from] += scat(to, from);
            }
            rows_.push_back(ScatteringRow(these_bounds.first,
                        these_bounds.second, &scat_[pos]));
            to++;
            pos += these_bounds.second-these_bounds.first+1;
        }

        // Check whether scat_ is reallocated
        assert( begin == scat_.data() );
    }

    std::ostream& operator<<( std::ostream& os,
            const ScatteringMatrix &scat_mat ) {
        for( auto &row: scat_mat.rows_ ) {
            int gmin = row.min_g;
            int gmax = row.max_g;
            for( int ig=0; ig<gmin; ig++ ) {
                os << std::setw(12) << 0.0;
            }

            for( int ig=gmin; ig<=gmax; ig++ ) {
                os << std::setw(12) << row[ig];
            }

            for( int ig=gmax+1; ig<scat_mat.ng_; ig++) {
                os << std::setw(12) << 0.0;
            }
            os << std::endl;
        }
        return os;
    }
}
<|endoftext|>


<commit_before>//===-- StructRetPromotion.cpp - Promote sret arguments ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass finds functions that return a struct (using a pointer to the struct
// as the first argument of the function, marked with the 'sret' attribute) and
// replaces them with a new function that simply returns each of the elements of
// that struct (using multiple return values).
//
// This pass works under a number of conditions:
//  1. The returned struct must not contain other structs
//  2. The returned struct must only be used to load values from
//  3. The placeholder struct passed in is the result of an alloca
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sretpromotion"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses");
STATISTIC(NumSRET , "Number of sret promoted");
namespace {
  /// SRETPromotion - This pass removes sret parameter and updates
  /// function to use multiple return value.
  ///
  struct SRETPromotion : public CallGraphSCCPass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      CallGraphSCCPass::getAnalysisUsage(AU);
    }

    virtual bool runOnSCC(CallGraphSCC &SCC);
    static char ID; // Pass identification, replacement for typeid
    SRETPromotion() : CallGraphSCCPass(ID) {}

  private:
    CallGraphNode *PromoteReturn(CallGraphNode *CGN);
    bool isSafeToUpdateAllCallers(Function *F);
    Function *cloneFunctionBody(Function *F, const StructType *STy);
    CallGraphNode *updateCallSites(Function *F, Function *NF);
    bool nestedStructType(const StructType *STy);
  };
}

char SRETPromotion::ID = 0;
INITIALIZE_PASS(SRETPromotion, "sretpromotion",
                "Promote sret arguments to multiple ret values", false, false);

Pass *llvm::createStructRetPromotionPass() {
  return new SRETPromotion();
}

bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) {
  bool Changed = false;

  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
    if (CallGraphNode *NewNode = PromoteReturn(*I)) {
      SCC.ReplaceNode(*I, NewNode);
      Changed = true;
    }

  return Changed;
}

/// PromoteReturn - This method promotes function that uses StructRet paramater
/// into a function that uses multiple return values.
CallGraphNode *SRETPromotion::PromoteReturn(CallGraphNode *CGN) {
  Function *F = CGN->getFunction();

  if (!F || F->isDeclaration() || !F->hasLocalLinkage())
    return 0;

  // Make sure that function returns struct.
  if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn())
    return 0;

  DEBUG(dbgs() << "SretPromotion: Looking at sret function "
        << F->getName() << "\n");

  assert(F->getReturnType()->isVoidTy() && "Invalid function return type");
  Function::arg_iterator AI = F->arg_begin();
  const llvm::PointerType *FArgType = dyn_cast<PointerType>(AI->getType());
  assert(FArgType && "Invalid sret parameter type");
  const llvm::StructType *STy =
    dyn_cast<StructType>(FArgType->getElementType());
  assert(STy && "Invalid sret parameter element type");

  // Check if it is ok to perform this promotion.
  if (isSafeToUpdateAllCallers(F) == false) {
    DEBUG(dbgs() << "SretPromotion: Not all callers can be updated\n");
    ++NumRejectedSRETUses;
    return 0;
  }

  DEBUG(dbgs() << "SretPromotion: sret argument will be promoted\n");
  ++NumSRET;
  // [1] Replace use of sret parameter
  AllocaInst *TheAlloca = new AllocaInst(STy, NULL, "mrv",
                                         F->getEntryBlock().begin());
  Value *NFirstArg = F->arg_begin();
  NFirstArg->replaceAllUsesWith(TheAlloca);

  // [2] Find and replace ret instructions
  for (Function::iterator FI = F->begin(), FE = F->end();  FI != FE; ++FI)
    for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) {
      Instruction *I = BI;
      ++BI;
      if (isa<ReturnInst>(I)) {
        Value *NV = new LoadInst(TheAlloca, "mrv.ld", I);
        ReturnInst *NR = ReturnInst::Create(F->getContext(), NV, I);
        I->replaceAllUsesWith(NR);
        I->eraseFromParent();
      }
    }

  // [3] Create the new function body and insert it into the module.
  Function *NF = cloneFunctionBody(F, STy);

  // [4] Update all call sites to use new function
  CallGraphNode *NF_CFN = updateCallSites(F, NF);

  CallGraph &CG = getAnalysis<CallGraph>();
  NF_CFN->stealCalledFunctionsFrom(CG[F]);

  delete CG.removeFunctionFromModule(F);
  return NF_CFN;
}

// Check if it is ok to perform this promotion.
bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) {

  if (F->use_empty())
    // No users. OK to modify signature.
    return true;

  for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end();
       FnUseI != FnUseE; ++FnUseI) {
    // The function is passed in as an argument to (possibly) another function,
    // we can't change it!
    CallSite CS(*FnUseI);
    Instruction *Call = CS.getInstruction();
    // The function is used by something else than a call or invoke instruction,
    // we can't change it!
    if (!Call || !CS.isCallee(FnUseI))
      return false;
    CallSite::arg_iterator AI = CS.arg_begin();
    Value *FirstArg = *AI;

    if (!isa<AllocaInst>(FirstArg))
      return false;

    // Check FirstArg's users.
    for (Value::use_iterator ArgI = FirstArg->use_begin(),
           ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) {
      User *U = *ArgI;
      // If FirstArg user is a CallInst that does not correspond to current
      // call site then this function F is not suitable for sret promotion.
      if (CallInst *CI = dyn_cast<CallInst>(U)) {
        if (CI != Call)
          return false;
      }
      // If FirstArg user is a GEP whose all users are not LoadInst then
      // this function F is not suitable for sret promotion.
      else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
        // TODO : Use dom info and insert PHINodes to collect get results
        // from multiple call sites for this GEP.
        if (GEP->getParent() != Call->getParent())
          return false;
        for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end();
             GEPI != GEPE; ++GEPI)
          if (!isa<LoadInst>(*GEPI))
            return false;
      }
      // Any other FirstArg users make this function unsuitable for sret
      // promotion.
      else
        return false;
    }
  }

  return true;
}

/// cloneFunctionBody - Create a new function based on F and
/// insert it into module. Remove first argument. Use STy as
/// the return type for new function.
Function *SRETPromotion::cloneFunctionBody(Function *F,
                                           const StructType *STy) {

  const FunctionType *FTy = F->getFunctionType();
  std::vector<const Type*> Params;

  // Attributes - Keep track of the parameter attributes for the arguments.
  SmallVector<AttributeWithIndex, 8> AttributesVec;
  const AttrListPtr &PAL = F->getAttributes();

  // Add any return attributes.
  if (Attributes attrs = PAL.getRetAttributes())
    AttributesVec.push_back(AttributeWithIndex::get(0, attrs));

  // Skip first argument.
  Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
  ++I;
  // 0th parameter attribute is reserved for return type.
  // 1th parameter attribute is for first 1st sret argument.
  unsigned ParamIndex = 2;
  while (I != E) {
    Params.push_back(I->getType());
    if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
      AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
    ++I;
    ++ParamIndex;
  }

  // Add any fn attributes.
  if (Attributes attrs = PAL.getFnAttributes())
    AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));

  FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg());
  Function *NF = Function::Create(NFTy, F->getLinkage());
  NF->takeName(F);
  NF->copyAttributesFrom(F);
  NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()));
  F->getParent()->getFunctionList().insert(F, NF);
  NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());

  // Replace arguments
  I = F->arg_begin();
  E = F->arg_end();
  Function::arg_iterator NI = NF->arg_begin();
  ++I;
  while (I != E) {
    I->replaceAllUsesWith(NI);
    NI->takeName(I);
    ++I;
    ++NI;
  }

  return NF;
}

/// updateCallSites - Update all sites that call F to use NF.
CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) {
  CallGraph &CG = getAnalysis<CallGraph>();
  SmallVector<Value*, 16> Args;

  // Attributes - Keep track of the parameter attributes for the arguments.
  SmallVector<AttributeWithIndex, 8> ArgAttrsVec;

  // Get a new callgraph node for NF.
  CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF);

  while (!F->use_empty()) {
    CallSite CS(*F->use_begin());
    Instruction *Call = CS.getInstruction();

    const AttrListPtr &PAL = F->getAttributes();
    // Add any return attributes.
    if (Attributes attrs = PAL.getRetAttributes())
      ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs));

    // Copy arguments, however skip first one.
    CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
    Value *FirstCArg = *AI;
    ++AI;
    // 0th parameter attribute is reserved for return type.
    // 1th parameter attribute is for first 1st sret argument.
    unsigned ParamIndex = 2;
    while (AI != AE) {
      Args.push_back(*AI);
      if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
        ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
      ++ParamIndex;
      ++AI;
    }

    // Add any function attributes.
    if (Attributes attrs = PAL.getFnAttributes())
      ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs));

    AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end());

    // Build new call instruction.
    Instruction *New;
    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
      New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
                               Args.begin(), Args.end(), "", Call);
      cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
      cast<InvokeInst>(New)->setAttributes(NewPAL);
    } else {
      New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call);
      cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
      cast<CallInst>(New)->setAttributes(NewPAL);
      if (cast<CallInst>(Call)->isTailCall())
        cast<CallInst>(New)->setTailCall();
    }
    Args.clear();
    ArgAttrsVec.clear();
    New->takeName(Call);

    // Update the callgraph to know that the callsite has been transformed.
    CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()];
    CalleeNode->removeCallEdgeFor(Call);
    CalleeNode->addCalledFunction(New, NF_CGN);

    // Update all users of sret parameter to extract value using extractvalue.
    for (Value::use_iterator UI = FirstCArg->use_begin(),
           UE = FirstCArg->use_end(); UI != UE; ) {
      User *U2 = *UI++;
      CallInst *C2 = dyn_cast<CallInst>(U2);
      if (C2 && (C2 == Call))
        continue;

      GetElementPtrInst *UGEP = cast<GetElementPtrInst>(U2);
      ConstantInt *Idx = cast<ConstantInt>(UGEP->getOperand(2));
      Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(),
                                           "evi", UGEP);
      while(!UGEP->use_empty()) {
        // isSafeToUpdateAllCallers has checked that all GEP uses are
        // LoadInsts
        LoadInst *L = cast<LoadInst>(*UGEP->use_begin());
        L->replaceAllUsesWith(GR);
        L->eraseFromParent();
      }
      UGEP->eraseFromParent();
      continue;
    }
    Call->eraseFromParent();
  }

  return NF_CGN;
}

/// nestedStructType - Return true if STy includes any
/// other aggregate types
bool SRETPromotion::nestedStructType(const StructType *STy) {
  unsigned Num = STy->getNumElements();
  for (unsigned i = 0; i < Num; i++) {
    const Type *Ty = STy->getElementType(i);
    if (!Ty->isSingleValueType() && !Ty->isVoidTy())
      return true;
  }
  return false;
}
<commit_msg>zap dead code.<commit_after>//===-- StructRetPromotion.cpp - Promote sret arguments -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass finds functions that return a struct (using a pointer to the struct
// as the first argument of the function, marked with the 'sret' attribute) and
// replaces them with a new function that simply returns each of the elements of
// that struct (using multiple return values).
//
// This pass works under a number of conditions:
//  1. The returned struct must not contain other structs
//  2. The returned struct must only be used to load values from
//  3. The placeholder struct passed in is the result of an alloca
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sretpromotion"
#include "llvm/Transforms/IPO.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/CallGraphSCCPass.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses");
STATISTIC(NumSRET , "Number of sret promoted");
namespace {
  /// SRETPromotion - This pass removes sret parameter and updates
  /// function to use multiple return value.
  ///
  struct SRETPromotion : public CallGraphSCCPass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      CallGraphSCCPass::getAnalysisUsage(AU);
    }

    virtual bool runOnSCC(CallGraphSCC &SCC);
    static char ID; // Pass identification, replacement for typeid
    SRETPromotion() : CallGraphSCCPass(ID) {}

  private:
    CallGraphNode *PromoteReturn(CallGraphNode *CGN);
    bool isSafeToUpdateAllCallers(Function *F);
    Function *cloneFunctionBody(Function *F, const StructType *STy);
    CallGraphNode *updateCallSites(Function *F, Function *NF);
  };
}

char SRETPromotion::ID = 0;
INITIALIZE_PASS(SRETPromotion, "sretpromotion",
                "Promote sret arguments to multiple ret values", false, false);

Pass *llvm::createStructRetPromotionPass() {
  return new SRETPromotion();
}

bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) {
  bool Changed = false;

  for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
    if (CallGraphNode *NewNode = PromoteReturn(*I)) {
      SCC.ReplaceNode(*I, NewNode);
      Changed = true;
    }

  return Changed;
}

/// PromoteReturn - This method promotes function that uses StructRet paramater
/// into a function that uses multiple return values.
CallGraphNode *SRETPromotion::PromoteReturn(CallGraphNode *CGN) {
  Function *F = CGN->getFunction();

  if (!F || F->isDeclaration() || !F->hasLocalLinkage())
    return 0;

  // Make sure that function returns struct.
  if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn())
    return 0;

  DEBUG(dbgs() << "SretPromotion: Looking at sret function "
        << F->getName() << "\n");

  assert(F->getReturnType()->isVoidTy() && "Invalid function return type");
  Function::arg_iterator AI = F->arg_begin();
  const llvm::PointerType *FArgType = dyn_cast<PointerType>(AI->getType());
  assert(FArgType && "Invalid sret parameter type");
  const llvm::StructType *STy =
    dyn_cast<StructType>(FArgType->getElementType());
  assert(STy && "Invalid sret parameter element type");

  // Check if it is ok to perform this promotion.
  if (isSafeToUpdateAllCallers(F) == false) {
    DEBUG(dbgs() << "SretPromotion: Not all callers can be updated\n");
    ++NumRejectedSRETUses;
    return 0;
  }

  DEBUG(dbgs() << "SretPromotion: sret argument will be promoted\n");
  ++NumSRET;
  // [1] Replace use of sret parameter
  AllocaInst *TheAlloca = new AllocaInst(STy, NULL, "mrv",
                                         F->getEntryBlock().begin());
  Value *NFirstArg = F->arg_begin();
  NFirstArg->replaceAllUsesWith(TheAlloca);

  // [2] Find and replace ret instructions
  for (Function::iterator FI = F->begin(), FE = F->end();  FI != FE; ++FI)
    for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) {
      Instruction *I = BI;
      ++BI;
      if (isa<ReturnInst>(I)) {
        Value *NV = new LoadInst(TheAlloca, "mrv.ld", I);
        ReturnInst *NR = ReturnInst::Create(F->getContext(), NV, I);
        I->replaceAllUsesWith(NR);
        I->eraseFromParent();
      }
    }

  // [3] Create the new function body and insert it into the module.
  Function *NF = cloneFunctionBody(F, STy);

  // [4] Update all call sites to use new function
  CallGraphNode *NF_CFN = updateCallSites(F, NF);

  CallGraph &CG = getAnalysis<CallGraph>();
  NF_CFN->stealCalledFunctionsFrom(CG[F]);

  delete CG.removeFunctionFromModule(F);
  return NF_CFN;
}

// Check if it is ok to perform this promotion.
bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) {

  if (F->use_empty())
    // No users. OK to modify signature.
    return true;

  for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end();
       FnUseI != FnUseE; ++FnUseI) {
    // The function is passed in as an argument to (possibly) another function,
    // we can't change it!
    CallSite CS(*FnUseI);
    Instruction *Call = CS.getInstruction();
    // The function is used by something else than a call or invoke instruction,
    // we can't change it!
    if (!Call || !CS.isCallee(FnUseI))
      return false;
    CallSite::arg_iterator AI = CS.arg_begin();
    Value *FirstArg = *AI;

    if (!isa<AllocaInst>(FirstArg))
      return false;

    // Check FirstArg's users.
    for (Value::use_iterator ArgI = FirstArg->use_begin(),
           ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) {
      User *U = *ArgI;
      // If FirstArg user is a CallInst that does not correspond to current
      // call site then this function F is not suitable for sret promotion.
      if (CallInst *CI = dyn_cast<CallInst>(U)) {
        if (CI != Call)
          return false;
      }
      // If FirstArg user is a GEP whose all users are not LoadInst then
      // this function F is not suitable for sret promotion.
      else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
        // TODO : Use dom info and insert PHINodes to collect get results
        // from multiple call sites for this GEP.
        if (GEP->getParent() != Call->getParent())
          return false;
        for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end();
             GEPI != GEPE; ++GEPI)
          if (!isa<LoadInst>(*GEPI))
            return false;
      }
      // Any other FirstArg users make this function unsuitable for sret
      // promotion.
      else
        return false;
    }
  }

  return true;
}

/// cloneFunctionBody - Create a new function based on F and
/// insert it into module. Remove first argument. Use STy as
/// the return type for new function.
Function *SRETPromotion::cloneFunctionBody(Function *F,
                                           const StructType *STy) {

  const FunctionType *FTy = F->getFunctionType();
  std::vector<const Type*> Params;

  // Attributes - Keep track of the parameter attributes for the arguments.
  SmallVector<AttributeWithIndex, 8> AttributesVec;
  const AttrListPtr &PAL = F->getAttributes();

  // Add any return attributes.
  if (Attributes attrs = PAL.getRetAttributes())
    AttributesVec.push_back(AttributeWithIndex::get(0, attrs));

  // Skip first argument.
  Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
  ++I;
  // 0th parameter attribute is reserved for return type.
  // 1th parameter attribute is for first 1st sret argument.
  unsigned ParamIndex = 2;
  while (I != E) {
    Params.push_back(I->getType());
    if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
      AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
    ++I;
    ++ParamIndex;
  }

  // Add any fn attributes.
  if (Attributes attrs = PAL.getFnAttributes())
    AttributesVec.push_back(AttributeWithIndex::get(~0, attrs));

  FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg());
  Function *NF = Function::Create(NFTy, F->getLinkage());
  NF->takeName(F);
  NF->copyAttributesFrom(F);
  NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()));
  F->getParent()->getFunctionList().insert(F, NF);
  NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList());

  // Replace arguments
  I = F->arg_begin();
  E = F->arg_end();
  Function::arg_iterator NI = NF->arg_begin();
  ++I;
  while (I != E) {
    I->replaceAllUsesWith(NI);
    NI->takeName(I);
    ++I;
    ++NI;
  }

  return NF;
}

/// updateCallSites - Update all sites that call F to use NF.
CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) {
  CallGraph &CG = getAnalysis<CallGraph>();
  SmallVector<Value*, 16> Args;

  // Attributes - Keep track of the parameter attributes for the arguments.
  SmallVector<AttributeWithIndex, 8> ArgAttrsVec;

  // Get a new callgraph node for NF.
  CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF);

  while (!F->use_empty()) {
    CallSite CS(*F->use_begin());
    Instruction *Call = CS.getInstruction();

    const AttrListPtr &PAL = F->getAttributes();
    // Add any return attributes.
    if (Attributes attrs = PAL.getRetAttributes())
      ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs));

    // Copy arguments, however skip first one.
    CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
    Value *FirstCArg = *AI;
    ++AI;
    // 0th parameter attribute is reserved for return type.
    // 1th parameter attribute is for first 1st sret argument.
    unsigned ParamIndex = 2;
    while (AI != AE) {
      Args.push_back(*AI);
      if (Attributes Attrs = PAL.getParamAttributes(ParamIndex))
        ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs));
      ++ParamIndex;
      ++AI;
    }

    // Add any function attributes.
    if (Attributes attrs = PAL.getFnAttributes())
      ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs));

    AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end());

    // Build new call instruction.
    Instruction *New;
    if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
      New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(),
                               Args.begin(), Args.end(), "", Call);
      cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
      cast<InvokeInst>(New)->setAttributes(NewPAL);
    } else {
      New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call);
      cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
      cast<CallInst>(New)->setAttributes(NewPAL);
      if (cast<CallInst>(Call)->isTailCall())
        cast<CallInst>(New)->setTailCall();
    }
    Args.clear();
    ArgAttrsVec.clear();
    New->takeName(Call);

    // Update the callgraph to know that the callsite has been transformed.
    CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()];
    CalleeNode->removeCallEdgeFor(Call);
    CalleeNode->addCalledFunction(New, NF_CGN);

    // Update all users of sret parameter to extract value using extractvalue.
    for (Value::use_iterator UI = FirstCArg->use_begin(),
           UE = FirstCArg->use_end(); UI != UE; ) {
      User *U2 = *UI++;
      CallInst *C2 = dyn_cast<CallInst>(U2);
      if (C2 && (C2 == Call))
        continue;

      GetElementPtrInst *UGEP = cast<GetElementPtrInst>(U2);
      ConstantInt *Idx = cast<ConstantInt>(UGEP->getOperand(2));
      Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(),
                                           "evi", UGEP);
      while(!UGEP->use_empty()) {
        // isSafeToUpdateAllCallers has checked that all GEP uses are
        // LoadInsts
        LoadInst *L = cast<LoadInst>(*UGEP->use_begin());
        L->replaceAllUsesWith(GR);
        L->eraseFromParent();
      }
      UGEP->eraseFromParent();
      continue;
    }
    Call->eraseFromParent();
  }

  return NF_CGN;
}

<|endoftext|>


<commit_before>
#pragma once

#include <string>
#include <list>
#include <vector>

#include <imgui.h>
#include "../ImGuiGf/IconsFontAwesome.h" // <- note required. just comment if not available

/** Helper class to deal with file paths.
*/
class MiniPath
{
private:
    std::string path {""};
    std::string name {""};

public:
    MiniPath( const std::string& some_path );
    MiniPath();

    void fromString (const std::string& file_path, char delim);
    void fromNameInCurrentDir( const std::string& file_name );

    std::string filePath() const;
    std::string prefix() const;
    std::string extension() const;

    std::string getName() const;
    std::string getPath() const;
    std::vector<std::string> getPathTokens() const;

    void setName( const std::string& name );
    bool setPath( const std::string& absolut_path );
    std::string getDelim() const;

    static std::string getCurrentDir();
    static std::string getSystemDelim();
    static bool isAbsoluteFilePath( const std::string& s );
    static std::string combine( const std::string& s1, const std::string& s2 );
    static std::list<std::string> listDirectories( const std::string& s );
    static std::list<std::string> listFiles( const std::string& s, std::string filter = "*.*" );
    static bool pathExists( const std::string& s );
};

/** Show a file-io dialoge window, e.g. usable as file save and file close dialoge.
Example - Save:
if( window_fileIO_visible )
{
    string save_file;
    if( fileIOWindow( save_file, window_recent_files, "Save", {"*.usr", "*.*"} ) )
    {
        window_fileIO_visible = false;
        if( !save_file.empty() )
        {
            window_recent_files.push_back( save_file );

            ofstream out_file;
            out_file.open( save_file, ios_base::trunc );
            writeStuffToFile( out_file );
            out_file.close();
        }
    }
}

Example - Open:
if( window_fileIO_visible )
{
    string open_file;
    if( fileIOWindow( open_file, window_recent_files, "Open", {"*.usr", "*.*"}, true  ) )
    {
        window_fileIO_visible = false;
        if( !open_file.empty() )
        {
            window_recent_files.push_back( open_file );
            readStuffFromFile( open_file );
        }
    }
}
*/
bool fileIOWindow(
    std::string& file_path,
    std::vector<std::string>& recently_used_files,
    const std::string& button_text,
    std::vector<std::string> file_filter = {"*.*"},
    bool ensure_file_exists = false,
    ImVec2 size = ImVec2(420,240) );
<commit_msg>change order, remove example code (as it is in the markdown anyways)<commit_after>
#pragma once

#include <string>
#include <list>
#include <vector>

#include <imgui.h>
#include "../ImGuiGf/IconsFontAwesome.h" // <- note required. just comment if not available

/** Show a file-io dialoge window, e.g. usable as file save and file close dialoge.
*/
bool fileIOWindow(
    std::string& file_path,
    std::vector<std::string>& recently_used_files,
    const std::string& button_text,
    std::vector<std::string> file_filter = {"*.*"},
    bool ensure_file_exists = false,
    ImVec2 size = ImVec2(420,240) );

/** Helper class to deal with file paths.
*/
class MiniPath
{
private:
    std::string path {""};
    std::string name {""};

public:
    MiniPath( const std::string& some_path );
    MiniPath();

    void fromString (const std::string& file_path, char delim);
    void fromNameInCurrentDir( const std::string& file_name );

    std::string filePath()  const;
    std::string prefix()    const;
    std::string extension() const;
    std::string getName()   const;
    std::string getPath()   const;
    std::vector<std::string> getPathTokens() const;

    void setName( const std::string& name );
    bool setPath( const std::string& absolut_path );
    std::string getDelim() const;

    static std::string getCurrentDir();
    static std::string getSystemDelim();
    static bool isAbsoluteFilePath( const std::string& s );
    static std::list<std::string> listDirectories( const std::string& s );
    static std::list<std::string> listFiles( const std::string& s, std::string filter = "*.*" );
    static bool pathExists( const std::string& s );
};

<|endoftext|>