summaryrefslogtreecommitdiffstats
path: root/polly/lib/Exchange/OpenScopImporter.cpp
blob: f96cc4104d229d461e76278b883daaeddd64c93e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
//===-- OpenScopImporter.cpp  - Import Scops with openscop library --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Import modified .scop files into Polly. This allows to change the schedule of
// statements.
//
//===----------------------------------------------------------------------===//

#include "polly/LinkAllPasses.h"
#include "polly/Dependences.h"
#include "polly/Options.h"
#include "polly/ScopInfo.h"
#include "polly/ScopPass.h"
#include "llvm/IR/Writer.h"

#ifdef OPENSCOP_FOUND

#define OPENSCOP_INT_T_IS_MP
#include "openscop/openscop.h"

#include "isl/map.h"
#include "isl/set.h"
#include "isl/constraint.h"

using namespace llvm;
using namespace polly;

namespace {
static cl::opt<std::string>
ImportDir("polly-import-dir",
          cl::desc("The directory to import the .scop files from."), cl::Hidden,
          cl::value_desc("Directory path"), cl::ValueRequired, cl::init("."));
static cl::opt<std::string>
ImportPostfix("polly-import-postfix",
              cl::desc("Postfix to append to the import .scop files."),
              cl::Hidden, cl::value_desc("File postfix"), cl::ValueRequired,
              cl::init(""));

struct ScopImporter : public ScopPass {
  static char ID;
  Scop *S;
  Dependences *D;
  explicit ScopImporter() : ScopPass(ID) {}
  bool updateScattering(Scop *S, openscop_scop_p OScop);

  std::string getFileName(Scop *S) const;
  virtual bool runOnScop(Scop &S);
  virtual void printScop(raw_ostream &OS) const;
  void getAnalysisUsage(AnalysisUsage &AU) const;
};
}

char ScopImporter::ID = 0;

/// @brief Create an isl constraint from a row of OpenScop integers.
///
/// @param row An array of isl/OpenScop integers.
/// @param Space An isl space object, describing how to spilt the dimensions.
///
/// @return An isl constraint representing this integer array.
isl_constraint *constraintFromMatrixRow(isl_int *row, isl_space *Space) {
  isl_constraint *c;

  unsigned NbOut = isl_space_size(Space, isl_dim_out);
  unsigned NbIn = isl_space_size(Space, isl_dim_in);
  unsigned NbParam = isl_space_size(Space, isl_dim_param);

  if (isl_int_is_zero(row[0]))
    c = isl_equality_alloc(isl_space_copy(Space));
  else
    c = isl_inequality_alloc(isl_space_copy(Space));

  unsigned current_column = 1;

  for (unsigned j = 0; j < NbOut; ++j)
    isl_constraint_set_coefficient(c, isl_space_out, j, row[current_column++]);

  for (unsigned j = 0; j < NbIn; ++j)
    isl_constraint_set_coefficient(c, isl_space_in, j, row[current_column++]);

  for (unsigned j = 0; j < NbParam; ++j)
    isl_constraint_set_coefficient(c, isl_space_param, j,
                                   row[current_column++]);

  isl_constraint_set_constant(c, row[current_column]);

  return c;
}

/// @brief Create an isl map from a OpenScop matrix.
///
/// @param m The OpenScop matrix to translate.
/// @param Space The dimensions that are contained in the OpenScop matrix.
///
/// @return An isl map representing m.
isl_map *mapFromMatrix(openscop_matrix_p m, isl_space *Space) {
  isl_basic_map *bmap = isl_basic_map_universe(isl_space_copy(Space));

  for (unsigned i = 0; i < m->NbRows; ++i) {
    isl_constraint *c;

    c = constraintFromMatrixRow(m->p[i], Space);
    bmap = isl_basic_map_add_constraint(bmap, c);
  }

  return isl_map_from_basic_map(bmap);
}

/// @brief Create a new scattering for PollyStmt.
///
/// @param m The matrix describing the new scattering.
/// @param PollyStmt The statement to create the scattering for.
///
/// @return An isl_map describing the scattering.
isl_map *scatteringForStmt(openscop_matrix_p m, ScopStmt *PollyStmt) {

  unsigned NbParam = PollyStmt->getNumParams();
  unsigned NbIterators = PollyStmt->getNumIterators();
  unsigned NbScattering = m->NbColumns - 2 - NbParam - NbIterators;

  isl_ctx *ctx = PollyStmt->getParent()->getCtx();
  isl_space *Space = isl_dim_alloc(ctx, NbParam, NbIterators, NbScattering);
  Space = isl_space_set_tuple_name(Space, isl_dim_out, "scattering");
  Space = isl_space_set_tuple_name(Space, isl_dim_in, PollyStmt->getBaseName());
  isl_map *map = mapFromMatrix(m, Space);
  isl_space_free(Space);

  return map;
}

typedef Dependences::StatementToIslMapTy StatementToIslMapTy;

/// @brief Read the new scattering from the OpenScop description.
///
/// @S      The Scop to update
/// @OScop  The OpenScop data structure describing the new scattering.
/// @return A map that contains for each Statement the new scattering.
StatementToIslMapTy *readScattering(Scop *S, openscop_scop_p OScop) {
  StatementToIslMapTy &NewScattering = *(new StatementToIslMapTy());
  openscop_statement_p stmt = OScop->statement;

  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
    if (!stmt) {
      errs() << "Not enough statements available in OpenScop file\n";
      delete &NewScattering;
      return NULL;
    }

    NewScattering[*SI] = scatteringForStmt(stmt->schedule, *SI);
    stmt = stmt->next;
  }

  if (stmt) {
    errs() << "Too many statements in OpenScop file\n";
    delete &NewScattering;
    return NULL;
  }

  return &NewScattering;
}

/// @brief Update the scattering in a Scop using the OpenScop description of
/// the scattering.
///
/// @S The Scop to update
/// @OScop The OpenScop data structure describing the new scattering.
/// @return Returns false, if the update failed.
bool ScopImporter::updateScattering(Scop *S, openscop_scop_p OScop) {
  StatementToIslMapTy *NewScattering = readScattering(S, OScop);

  if (!NewScattering)
    return false;

  if (!D->isValidScattering(NewScattering)) {
    errs() << "OpenScop file contains a scattering that changes the "
           << "dependences. Use -disable-polly-legality to continue anyways\n";
    return false;
  }

  for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) {
    ScopStmt *Stmt = *SI;

    if (NewScattering->find(Stmt) != NewScattering->end())
      Stmt->setScattering((*NewScattering)[Stmt]);
  }

  return true;
}
std::string ScopImporter::getFileName(Scop *S) const {
  std::string FunctionName = S->getRegion().getEntry()->getParent()->getName();
  std::string FileName = FunctionName + "___" + S->getNameStr() + ".scop";
  return FileName;
}

void ScopImporter::printScop(raw_ostream &OS) const { S->print(OS); }

bool ScopImporter::runOnScop(Scop &scop) {
  S = &scop;
  Region &R = scop.getRegion();
  D = &getAnalysis<Dependences>();

  std::string FileName = ImportDir + "/" + getFileName(S) + ImportPostfix;
  FILE *F = fopen(FileName.c_str(), "r");

  if (!F) {
    errs() << "Cannot open file: " << FileName << "\n";
    errs() << "Skipping import.\n";
    return false;
  }

  openscop_scop_p openscop = openscop_scop_read(F);
  fclose(F);

  std::string FunctionName = R.getEntry()->getParent()->getName();
  errs() << "Reading Scop '" << R.getNameStr() << "' in function '"
         << FunctionName << "' from '" << FileName << "'.\n";

  bool UpdateSuccessfull = updateScattering(S, openscop);

  if (!UpdateSuccessfull) {
    errs() << "Update failed"
           << "\n";
  }

  return false;
}

void ScopImporter::getAnalysisUsage(AnalysisUsage &AU) const {
  ScopPass::getAnalysisUsage(AU);
  AU.addRequired<Dependences>();
}

static RegisterPass<ScopImporter> A("polly-import",
                                    "Polly - Import Scops with OpenScop library"
                                    " (Reads a .scop file for each Scop)");

Pass *polly::createScopImporterPass() { return new ScopImporter(); }

#endif
OpenPOWER on IntegriCloud