Skip to content

Commit

Permalink
[JSON][PM] Port json import/export over to new pm
Browse files Browse the repository at this point in the history
Summary:
I pulled out all functionality into static functions, and use those both
in the legacy passes and in the new ones.

Reviewers: grosser, Meinersbur, bollu

Reviewed By: Meinersbur

Subscribers: llvm-commits, pollydev

Differential Revision: https://reviews.llvm.org/D36578

llvm-svn: 310597
  • Loading branch information
pfaffe committed Aug 10, 2017
1 parent 925c074 commit 47bf15c
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 97 deletions.
23 changes: 23 additions & 0 deletions polly/include/polly/JSONExporter.h
@@ -0,0 +1,23 @@
#ifndef POLLY_JSONEXPORTER_H
#define POLLY_JSONEXPORTER_H

#include "polly/ScopPass.h"
#include "llvm/IR/PassManager.h"

namespace polly {
/// This pass exports a scop to a jscop file. The filename is generated from the
/// concatenation of the function and scop name.
struct JSONExportPass : public llvm::PassInfoMixin<JSONExportPass> {
llvm::PreservedAnalyses run(Scop &, ScopAnalysisManager &,
ScopStandardAnalysisResults &, SPMUpdater &);
};

/// This pass imports a scop from a jscop file. The filename is deduced from the
/// concatenation of the function and scop name.
struct JSONImportPass : public llvm::PassInfoMixin<JSONExportPass> {
llvm::PreservedAnalyses run(Scop &, ScopAnalysisManager &,
ScopStandardAnalysisResults &, SPMUpdater &);
};
} // namespace polly

#endif /* POLLY_JSONEXPORTER_H */
217 changes: 121 additions & 96 deletions polly/lib/Exchange/JSONExporter.cpp
Expand Up @@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//

#include "polly/JSONExporter.h"
#include "polly/DependenceInfo.h"
#include "polly/LinkAllPasses.h"
#include "polly/Options.h"
Expand Down Expand Up @@ -59,9 +60,6 @@ struct JSONExporter : public ScopPass {
static char ID;
explicit JSONExporter() : ScopPass(ID) {}

std::string getFileName(Scop &S) const;
Json::Value getJSON(Scop &S) const;

/// Export the SCoP @p S to a JSON file.
bool runOnScop(Scop &S) override;

Expand All @@ -76,46 +74,6 @@ struct JSONImporter : public ScopPass {
static char ID;
std::vector<std::string> NewAccessStrings;
explicit JSONImporter() : ScopPass(ID) {}

/// Import a new context from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
///
/// @returns True if the import succeeded, otherwise False.
bool importContext(Scop &S, Json::Value &JScop);

/// Import a new schedule from JScop.
///
/// ... and verify that the new schedule does preserve existing data
/// dependences.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
/// @param D The data dependences of the @p S.
///
/// @returns True if the import succeeded, otherwise False.
bool importSchedule(Scop &S, Json::Value &JScop, const Dependences &D);

/// Import new arrays from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing new arrays.
///
/// @returns True if the import succeeded, otherwise False.
bool importArrays(Scop &S, Json::Value &JScop);

/// Import new memory accesses from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
/// @param DL The data layout to assume.
///
/// @returns True if the import succeeded, otherwise False.
bool importAccesses(Scop &S, Json::Value &JScop, const DataLayout &DL);

std::string getFileName(Scop &S) const;

/// Import new access functions for SCoP @p S from a JSON file.
bool runOnScop(Scop &S) override;

Expand All @@ -127,21 +85,22 @@ struct JSONImporter : public ScopPass {
};
} // namespace

char JSONExporter::ID = 0;
std::string JSONExporter::getFileName(Scop &S) const {
static std::string getFileName(Scop &S, StringRef Suffix = "") {
std::string FunctionName = S.getFunction().getName();
std::string FileName = FunctionName + "___" + S.getNameStr() + ".jscop";

if (Suffix != "")
FileName += "." + Suffix.str();

return FileName;
}

void JSONExporter::printScop(raw_ostream &OS, Scop &S) const { OS << S; }

/// Export all arrays from the Scop.
///
/// @param S The Scop containing the arrays.
///
/// @returns Json::Value containing the arrays.
Json::Value exportArrays(const Scop &S) {
static Json::Value exportArrays(const Scop &S) {
Json::Value Arrays;
std::string Buffer;
llvm::raw_string_ostream RawStringOstream(Buffer);
Expand Down Expand Up @@ -170,7 +129,7 @@ Json::Value exportArrays(const Scop &S) {
return Arrays;
}

Json::Value JSONExporter::getJSON(Scop &S) const {
static Json::Value getJSON(Scop &S) {
Json::Value root;
unsigned LineBegin, LineEnd;
std::string FileName;
Expand Down Expand Up @@ -213,7 +172,7 @@ Json::Value JSONExporter::getJSON(Scop &S) const {
return root;
}

bool JSONExporter::runOnScop(Scop &S) {
static void exportScop(Scop &S) {
std::string FileName = ImportDir + "/" + getFileName(S);

Json::Value jscop = getJSON(S);
Expand All @@ -234,45 +193,23 @@ bool JSONExporter::runOnScop(Scop &S) {
if (!F.os().has_error()) {
errs() << "\n";
F.keep();
return false;
return;
}
}

errs() << " error opening file for writing!\n";
F.os().clear_error();

return false;
}

void JSONExporter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<ScopInfoRegionPass>();
}

Pass *polly::createJSONExporterPass() { return new JSONExporter(); }

char JSONImporter::ID = 0;
std::string JSONImporter::getFileName(Scop &S) const {
std::string FunctionName = S.getFunction().getName();
std::string FileName = FunctionName + "___" + S.getNameStr() + ".jscop";

if (ImportPostfix != "")
FileName += "." + ImportPostfix;

return FileName;
}

void JSONImporter::printScop(raw_ostream &OS, Scop &S) const {
OS << S;
for (std::vector<std::string>::const_iterator I = NewAccessStrings.begin(),
E = NewAccessStrings.end();
I != E; I++)
OS << "New access function '" << *I << "' detected in JSCOP file\n";
}

typedef Dependences::StatementToIslMapTy StatementToIslMapTy;

bool JSONImporter::importContext(Scop &S, Json::Value &JScop) {
/// Import a new context from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
///
/// @returns True if the import succeeded, otherwise False.
static bool importContext(Scop &S, Json::Value &JScop) {
isl_set *OldContext = S.getContext().release();

// Check if key 'context' is present.
Expand Down Expand Up @@ -324,8 +261,17 @@ bool JSONImporter::importContext(Scop &S, Json::Value &JScop) {
return true;
}

bool JSONImporter::importSchedule(Scop &S, Json::Value &JScop,
const Dependences &D) {
/// Import a new schedule from JScop.
///
/// ... and verify that the new schedule does preserve existing data
/// dependences.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
/// @param D The data dependences of the @p S.
///
/// @returns True if the import succeeded, otherwise False.
static bool importSchedule(Scop &S, Json::Value &JScop, const Dependences &D) {
StatementToIslMapTy NewSchedule;

// Check if key 'statements' is present.
Expand Down Expand Up @@ -405,8 +351,17 @@ bool JSONImporter::importSchedule(Scop &S, Json::Value &JScop,
return true;
}

bool JSONImporter::importAccesses(Scop &S, Json::Value &JScop,
const DataLayout &DL) {
/// Import new memory accesses from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing the new schedule.
/// @param DL The data layout to assume.
/// @param NewAccessStrings optionally record the imported access strings
///
/// @returns True if the import succeeded, otherwise False.
static bool
importAccesses(Scop &S, Json::Value &JScop, const DataLayout &DL,
std::vector<std::string> *NewAccessStrings = nullptr) {
int StatementIdx = 0;

// Check if key 'statements' is present.
Expand Down Expand Up @@ -582,7 +537,8 @@ bool JSONImporter::importAccesses(Scop &S, Json::Value &JScop,
if (!isl_map_is_equal(NewAccessMap, CurrentAccessMap)) {
// Statistics.
++NewAccessMapFound;
NewAccessStrings.push_back(Accesses.asCString());
if (NewAccessStrings)
NewAccessStrings->push_back(Accesses.asCString());
MA->setNewAccessRelation(isl::manage(NewAccessMap));
} else {
isl_map_free(NewAccessMap);
Expand All @@ -597,7 +553,7 @@ bool JSONImporter::importAccesses(Scop &S, Json::Value &JScop,
}

/// Check whether @p SAI and @p Array represent the same array.
bool areArraysEqual(ScopArrayInfo *SAI, Json::Value Array) {
static bool areArraysEqual(ScopArrayInfo *SAI, Json::Value Array) {
std::string Buffer;
llvm::raw_string_ostream RawStringOstream(Buffer);

Expand Down Expand Up @@ -648,8 +604,8 @@ bool areArraysEqual(ScopArrayInfo *SAI, Json::Value Array) {
/// @param TypeTextRepresentation The textual representation of the type.
/// @return The pointer to the primitive type, if this type is accepted
/// or nullptr otherwise.
Type *parseTextType(const std::string &TypeTextRepresentation,
LLVMContext &LLVMContext) {
static Type *parseTextType(const std::string &TypeTextRepresentation,
LLVMContext &LLVMContext) {
std::map<std::string, Type *> MapStrToType = {
{"void", Type::getVoidTy(LLVMContext)},
{"half", Type::getHalfTy(LLVMContext)},
Expand All @@ -674,7 +630,13 @@ Type *parseTextType(const std::string &TypeTextRepresentation,
return nullptr;
}

bool JSONImporter::importArrays(Scop &S, Json::Value &JScop) {
/// Import new arrays from JScop.
///
/// @param S The scop to update.
/// @param JScop The JScop file describing new arrays.
///
/// @returns True if the import succeeded, otherwise False.
static bool importArrays(Scop &S, Json::Value &JScop) {
Json::Value Arrays = JScop["arrays"];
if (Arrays.size() == 0)
return true;
Expand Down Expand Up @@ -726,12 +688,18 @@ bool JSONImporter::importArrays(Scop &S, Json::Value &JScop) {
return true;
}

bool JSONImporter::runOnScop(Scop &S) {
const Dependences &D =
getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement);
const DataLayout &DL = S.getFunction().getParent()->getDataLayout();

std::string FileName = ImportDir + "/" + getFileName(S);
/// Import a Scop from a JSCOP file
/// @param S The scop to be modified
/// @param D Dependence Info
/// @param DL The DataLayout of the function
/// @param NewAccessStrings Optionally record the imported access strings
///
/// @returns true on success, false otherwise. Beware that if this returns
/// false, the Scop may still have been modified. In this case the Scop contains
/// invalid information.
static bool importScop(Scop &S, const Dependences &D, const DataLayout &DL,
std::vector<std::string> *NewAccessStrings = nullptr) {
std::string FileName = ImportDir + "/" + getFileName(S, ImportPostfix);

std::string FunctionName = S.getFunction().getName();
errs() << "Reading JScop '" << S.getNameStr() << "' in function '"
Expand Down Expand Up @@ -770,11 +738,50 @@ bool JSONImporter::runOnScop(Scop &S) {
if (!Success)
return false;

Success = importAccesses(S, jscop, DL);
Success = importAccesses(S, jscop, DL, NewAccessStrings);

if (!Success)
return false;
return true;
}

char JSONExporter::ID = 0;
void JSONExporter::printScop(raw_ostream &OS, Scop &S) const { OS << S; }

bool JSONExporter::runOnScop(Scop &S) {
exportScop(S);
return false;
}

void JSONExporter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<ScopInfoRegionPass>();
}

Pass *polly::createJSONExporterPass() { return new JSONExporter(); }

PreservedAnalyses JSONExportPass::run(Scop &S, ScopAnalysisManager &SAM,
ScopStandardAnalysisResults &SAR,
SPMUpdater &) {
exportScop(S);
return PreservedAnalyses::all();
}

char JSONImporter::ID = 0;

void JSONImporter::printScop(raw_ostream &OS, Scop &S) const {
OS << S;
for (std::vector<std::string>::const_iterator I = NewAccessStrings.begin(),
E = NewAccessStrings.end();
I != E; I++)
OS << "New access function '" << *I << "' detected in JSCOP file\n";
}

bool JSONImporter::runOnScop(Scop &S) {
const Dependences &D =
getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement);
const DataLayout &DL = S.getFunction().getParent()->getDataLayout();
importScop(S, D, DL, &NewAccessStrings);
return false;
}

Expand All @@ -785,6 +792,24 @@ void JSONImporter::getAnalysisUsage(AnalysisUsage &AU) const {

Pass *polly::createJSONImporterPass() { return new JSONImporter(); }

PreservedAnalyses JSONImportPass::run(Scop &S, ScopAnalysisManager &SAM,
ScopStandardAnalysisResults &SAR,
SPMUpdater &) {
const Dependences &D =
SAM.getResult<DependenceAnalysis>(S, SAR).getDependences(
Dependences::AL_Statement);
const DataLayout &DL = S.getFunction().getParent()->getDataLayout();

importScop(S, D, DL);

// This invalidates all analyses on Scop.
PreservedAnalyses PA;
PA.preserveSet<AllAnalysesOn<Module>>();
PA.preserveSet<AllAnalysesOn<Function>>();
PA.preserveSet<AllAnalysesOn<Loop>>();
return PA;
}

INITIALIZE_PASS_BEGIN(JSONExporter, "polly-export-jscop",
"Polly - Export Scops as JSON"
" (Writes a .jscop file for each Scop)",
Expand Down
2 changes: 2 additions & 0 deletions polly/lib/Support/PollyPasses.def
Expand Up @@ -23,6 +23,8 @@ SCOP_ANALYSIS("polly-dependences", DependenceAnalysis())
#ifndef SCOP_PASS
#define SCOP_PASS(NAME, CREATE_PASS)
#endif
SCOP_PASS("polly-export-jscop", JSONExportPass())
SCOP_PASS("polly-import-jscop", JSONImportPass())
SCOP_PASS("print<polly-ast>", IslAstPrinterPass(outs()))
SCOP_PASS("print<polly-dependences>", DependenceInfoPrinterPass(outs()))
SCOP_PASS("polly-codegen", CodeGenerationPass())
Expand Down

0 comments on commit 47bf15c

Please sign in to comment.