Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/Analysis/ScopInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ScopInfo.cpp -------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Create a polyhedral description for a static control flow region.
10
//
11
// The pass creates a polyhedral description of the Scops detected by the Scop
12
// detection derived from their LLVM-IR code.
13
//
14
// This representation is shared among several tools in the polyhedral
15
// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
16
//
17
//===----------------------------------------------------------------------===//
18
19
#include "polly/ScopInfo.h"
20
#include "polly/LinkAllPasses.h"
21
#include "polly/Options.h"
22
#include "polly/ScopBuilder.h"
23
#include "polly/ScopDetection.h"
24
#include "polly/Support/GICHelper.h"
25
#include "polly/Support/ISLOStream.h"
26
#include "polly/Support/ISLTools.h"
27
#include "polly/Support/SCEVAffinator.h"
28
#include "polly/Support/SCEVValidator.h"
29
#include "polly/Support/ScopHelper.h"
30
#include "llvm/ADT/APInt.h"
31
#include "llvm/ADT/ArrayRef.h"
32
#include "llvm/ADT/PostOrderIterator.h"
33
#include "llvm/ADT/SmallPtrSet.h"
34
#include "llvm/ADT/SmallSet.h"
35
#include "llvm/ADT/Statistic.h"
36
#include "llvm/Analysis/AliasAnalysis.h"
37
#include "llvm/Analysis/AssumptionCache.h"
38
#include "llvm/Analysis/Loads.h"
39
#include "llvm/Analysis/LoopInfo.h"
40
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
41
#include "llvm/Analysis/RegionInfo.h"
42
#include "llvm/Analysis/RegionIterator.h"
43
#include "llvm/Analysis/ScalarEvolution.h"
44
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
45
#include "llvm/IR/BasicBlock.h"
46
#include "llvm/IR/ConstantRange.h"
47
#include "llvm/IR/DataLayout.h"
48
#include "llvm/IR/DebugLoc.h"
49
#include "llvm/IR/Dominators.h"
50
#include "llvm/IR/Function.h"
51
#include "llvm/IR/InstrTypes.h"
52
#include "llvm/IR/Instruction.h"
53
#include "llvm/IR/Instructions.h"
54
#include "llvm/IR/Module.h"
55
#include "llvm/IR/PassManager.h"
56
#include "llvm/IR/Type.h"
57
#include "llvm/IR/Value.h"
58
#include "llvm/Support/Compiler.h"
59
#include "llvm/Support/Debug.h"
60
#include "llvm/Support/ErrorHandling.h"
61
#include "llvm/Support/raw_ostream.h"
62
#include "isl/aff.h"
63
#include "isl/local_space.h"
64
#include "isl/map.h"
65
#include "isl/options.h"
66
#include "isl/set.h"
67
#include <cassert>
68
69
using namespace llvm;
70
using namespace polly;
71
72
689
#define DEBUG_TYPE "polly-scops"
73
74
STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken.");
75
STATISTIC(AssumptionsInbounds, "Number of inbounds assumptions taken.");
76
STATISTIC(AssumptionsWrapping, "Number of wrapping assumptions taken.");
77
STATISTIC(AssumptionsUnsigned, "Number of unsigned assumptions taken.");
78
STATISTIC(AssumptionsComplexity, "Number of too complex SCoPs.");
79
STATISTIC(AssumptionsUnprofitable, "Number of unprofitable SCoPs.");
80
STATISTIC(AssumptionsErrorBlock, "Number of error block assumptions taken.");
81
STATISTIC(AssumptionsInfiniteLoop, "Number of bounded loop assumptions taken.");
82
STATISTIC(AssumptionsInvariantLoad,
83
          "Number of invariant loads assumptions taken.");
84
STATISTIC(AssumptionsDelinearization,
85
          "Number of delinearization assumptions taken.");
86
87
STATISTIC(NumScops, "Number of feasible SCoPs after ScopInfo");
88
STATISTIC(NumLoopsInScop, "Number of loops in scops");
89
STATISTIC(NumBoxedLoops, "Number of boxed loops in SCoPs after ScopInfo");
90
STATISTIC(NumAffineLoops, "Number of affine loops in SCoPs after ScopInfo");
91
92
STATISTIC(NumScopsDepthZero, "Number of scops with maximal loop depth 0");
93
STATISTIC(NumScopsDepthOne, "Number of scops with maximal loop depth 1");
94
STATISTIC(NumScopsDepthTwo, "Number of scops with maximal loop depth 2");
95
STATISTIC(NumScopsDepthThree, "Number of scops with maximal loop depth 3");
96
STATISTIC(NumScopsDepthFour, "Number of scops with maximal loop depth 4");
97
STATISTIC(NumScopsDepthFive, "Number of scops with maximal loop depth 5");
98
STATISTIC(NumScopsDepthLarger,
99
          "Number of scops with maximal loop depth 6 and larger");
100
STATISTIC(MaxNumLoopsInScop, "Maximal number of loops in scops");
101
102
STATISTIC(NumValueWrites, "Number of scalar value writes after ScopInfo");
103
STATISTIC(
104
    NumValueWritesInLoops,
105
    "Number of scalar value writes nested in affine loops after ScopInfo");
106
STATISTIC(NumPHIWrites, "Number of scalar phi writes after ScopInfo");
107
STATISTIC(NumPHIWritesInLoops,
108
          "Number of scalar phi writes nested in affine loops after ScopInfo");
109
STATISTIC(NumSingletonWrites, "Number of singleton writes after ScopInfo");
110
STATISTIC(NumSingletonWritesInLoops,
111
          "Number of singleton writes nested in affine loops after ScopInfo");
112
113
int const polly::MaxDisjunctsInDomain = 20;
114
115
// The number of disjunct in the context after which we stop to add more
116
// disjuncts. This parameter is there to avoid exponential growth in the
117
// number of disjunct when adding non-convex sets to the context.
118
static int const MaxDisjunctsInContext = 4;
119
120
static cl::opt<bool> PollyRemarksMinimal(
121
    "polly-remarks-minimal",
122
    cl::desc("Do not emit remarks about assumptions that are known"),
123
    cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory));
124
125
static cl::opt<bool>
126
    IslOnErrorAbort("polly-on-isl-error-abort",
127
                    cl::desc("Abort if an isl error is encountered"),
128
                    cl::init(true), cl::cat(PollyCategory));
129
130
static cl::opt<bool> PollyPreciseInbounds(
131
    "polly-precise-inbounds",
132
    cl::desc("Take more precise inbounds assumptions (do not scale well)"),
133
    cl::Hidden, cl::init(false), cl::cat(PollyCategory));
134
135
static cl::opt<bool>
136
    PollyIgnoreInbounds("polly-ignore-inbounds",
137
                        cl::desc("Do not take inbounds assumptions at all"),
138
                        cl::Hidden, cl::init(false), cl::cat(PollyCategory));
139
140
static cl::opt<bool> PollyIgnoreParamBounds(
141
    "polly-ignore-parameter-bounds",
142
    cl::desc(
143
        "Do not add parameter bounds and do no gist simplify sets accordingly"),
144
    cl::Hidden, cl::init(false), cl::cat(PollyCategory));
145
146
static cl::opt<bool> PollyPreciseFoldAccesses(
147
    "polly-precise-fold-accesses",
148
    cl::desc("Fold memory accesses to model more possible delinearizations "
149
             "(does not scale well)"),
150
    cl::Hidden, cl::init(false), cl::cat(PollyCategory));
151
152
bool polly::UseInstructionNames;
153
154
static cl::opt<bool, true> XUseInstructionNames(
155
    "polly-use-llvm-names",
156
    cl::desc("Use LLVM-IR names when deriving statement names"),
157
    cl::location(UseInstructionNames), cl::Hidden, cl::init(false),
158
    cl::ZeroOrMore, cl::cat(PollyCategory));
159
160
static cl::opt<bool> PollyPrintInstructions(
161
    "polly-print-instructions", cl::desc("Output instructions per ScopStmt"),
162
    cl::Hidden, cl::Optional, cl::init(false), cl::cat(PollyCategory));
163
164
//===----------------------------------------------------------------------===//
165
166
static isl::set addRangeBoundsToSet(isl::set S, const ConstantRange &Range,
167
1.22k
                                    int dim, isl::dim type) {
168
1.22k
  isl::val V;
169
1.22k
  isl::ctx Ctx = S.get_ctx();
170
1.22k
171
1.22k
  // The upper and lower bound for a parameter value is derived either from
172
1.22k
  // the data type of the parameter or from the - possibly more restrictive -
173
1.22k
  // range metadata.
174
1.22k
  V = valFromAPInt(Ctx.get(), Range.getSignedMin(), true);
175
1.22k
  S = S.lower_bound_val(type, dim, V);
176
1.22k
  V = valFromAPInt(Ctx.get(), Range.getSignedMax(), true);
177
1.22k
  S = S.upper_bound_val(type, dim, V);
178
1.22k
179
1.22k
  if (Range.isFullSet())
180
1.14k
    return S;
181
77
182
77
  if (S.n_basic_set() > MaxDisjunctsInContext)
183
13
    return S;
184
64
185
64
  // In case of signed wrapping, we can refine the set of valid values by
186
64
  // excluding the part not covered by the wrapping range.
187
64
  if (Range.isSignWrappedSet()) {
188
7
    V = valFromAPInt(Ctx.get(), Range.getLower(), true);
189
7
    isl::set SLB = S.lower_bound_val(type, dim, V);
190
7
191
7
    V = valFromAPInt(Ctx.get(), Range.getUpper(), true);
192
7
    V = V.sub_ui(1);
193
7
    isl::set SUB = S.upper_bound_val(type, dim, V);
194
7
    S = SLB.unite(SUB);
195
7
  }
196
64
197
64
  return S;
198
64
}
199
200
1.83k
static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) {
201
1.83k
  LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr);
202
1.83k
  if (!BasePtrLI)
203
1.68k
    return nullptr;
204
156
205
156
  if (!S->contains(BasePtrLI))
206
63
    return nullptr;
207
93
208
93
  ScalarEvolution &SE = *S->getSE();
209
93
210
93
  auto *OriginBaseSCEV =
211
93
      SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand()));
212
93
  if (!OriginBaseSCEV)
213
0
    return nullptr;
214
93
215
93
  auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV);
216
93
  if (!OriginBaseSCEVUnknown)
217
0
    return nullptr;
218
93
219
93
  return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(),
220
93
                             MemoryKind::Array);
221
93
}
222
223
ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx Ctx,
224
                             ArrayRef<const SCEV *> Sizes, MemoryKind Kind,
225
                             const DataLayout &DL, Scop *S,
226
                             const char *BaseName)
227
2.57k
    : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) {
228
2.57k
  std::string BasePtrName =
229
2.57k
      BaseName ? 
BaseName85
230
2.57k
               : getIslCompatibleName("MemRef", BasePtr, S->getNextArrayIdx(),
231
2.48k
                                      Kind == MemoryKind::PHI ? 
"__phi"231
:
""2.25k
,
232
2.48k
                                      UseInstructionNames);
233
2.57k
  Id = isl::id::alloc(Ctx, BasePtrName, this);
234
2.57k
235
2.57k
  updateSizes(Sizes);
236
2.57k
237
2.57k
  if (!BasePtr || 
Kind != MemoryKind::Array2.48k
) {
238
734
    BasePtrOriginSAI = nullptr;
239
734
    return;
240
734
  }
241
1.83k
242
1.83k
  BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
243
1.83k
  if (BasePtrOriginSAI)
244
93
    const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
245
1.83k
}
246
247
2.53k
ScopArrayInfo::~ScopArrayInfo() = default;
248
249
5.30k
isl::space ScopArrayInfo::getSpace() const {
250
5.30k
  auto Space = isl::space(Id.get_ctx(), 0, getNumberOfDimensions());
251
5.30k
  Space = Space.set_tuple_id(isl::dim::set, Id);
252
5.30k
  return Space;
253
5.30k
}
254
255
0
bool ScopArrayInfo::isReadOnly() {
256
0
  isl::union_set WriteSet = S.getWrites().range();
257
0
  isl::space Space = getSpace();
258
0
  WriteSet = WriteSet.extract_set(Space);
259
0
260
0
  return bool(WriteSet.is_empty());
261
0
}
262
263
14
bool ScopArrayInfo::isCompatibleWith(const ScopArrayInfo *Array) const {
264
14
  if (Array->getElementType() != getElementType())
265
1
    return false;
266
13
267
13
  if (Array->getNumberOfDimensions() != getNumberOfDimensions())
268
1
    return false;
269
12
270
24
  
for (unsigned i = 0; 12
i < getNumberOfDimensions();
i++12
)
271
13
    if (Array->getDimensionSize(i) != getDimensionSize(i))
272
1
      return false;
273
12
274
12
  
return true11
;
275
12
}
276
277
5.38k
void ScopArrayInfo::updateElementType(Type *NewElementType) {
278
5.38k
  if (NewElementType == ElementType)
279
4.20k
    return;
280
1.18k
281
1.18k
  auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType);
282
1.18k
  auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType);
283
1.18k
284
1.18k
  if (NewElementSize == OldElementSize || 
NewElementSize == 056
)
285
1.12k
    return;
286
56
287
56
  if (NewElementSize % OldElementSize == 0 && 
NewElementSize < OldElementSize28
) {
288
0
    ElementType = NewElementType;
289
56
  } else {
290
56
    auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize);
291
56
    ElementType = IntegerType::get(ElementType->getContext(), GCD);
292
56
  }
293
56
}
294
295
/// Make the ScopArrayInfo model a Fortran Array
296
10
void ScopArrayInfo::applyAndSetFAD(Value *FAD) {
297
10
  assert(FAD && "got invalid Fortran array descriptor");
298
10
  if (this->FAD) {
299
3
    assert(this->FAD == FAD &&
300
3
           "receiving different array descriptors for same array");
301
3
    return;
302
3
  }
303
7
304
7
  assert(DimensionSizesPw.size() > 0 && !DimensionSizesPw[0]);
305
7
  assert(!this->FAD);
306
7
  this->FAD = FAD;
307
7
308
7
  isl::space Space(S.getIslCtx(), 1, 0);
309
7
310
7
  std::string param_name = getName();
311
7
  param_name += "_fortranarr_size";
312
7
  isl::id IdPwAff = isl::id::alloc(S.getIslCtx(), param_name, this);
313
7
314
7
  Space = Space.set_dim_id(isl::dim::param, 0, IdPwAff);
315
7
  isl::pw_aff PwAff =
316
7
      isl::aff::var_on_domain(isl::local_space(Space), isl::dim::param, 0);
317
7
318
7
  DimensionSizesPw[0] = PwAff;
319
7
}
320
321
bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes,
322
5.00k
                                bool CheckConsistency) {
323
5.00k
  int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
324
5.00k
  int ExtraDimsNew = NewSizes.size() - SharedDims;
325
5.00k
  int ExtraDimsOld = DimensionSizes.size() - SharedDims;
326
5.00k
327
5.00k
  if (CheckConsistency) {
328
6.76k
    for (int i = 0; i < SharedDims; 
i++1.77k
) {
329
1.77k
      auto *NewSize = NewSizes[i + ExtraDimsNew];
330
1.77k
      auto *KnownSize = DimensionSizes[i + ExtraDimsOld];
331
1.77k
      if (NewSize && 
KnownSize183
&&
NewSize != KnownSize177
)
332
0
        return false;
333
1.77k
    }
334
4.99k
335
4.99k
    if (DimensionSizes.size() >= NewSizes.size())
336
3.06k
      return true;
337
1.93k
  }
338
1.93k
339
1.93k
  DimensionSizes.clear();
340
1.93k
  DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(),
341
1.93k
                        NewSizes.end());
342
1.93k
  DimensionSizesPw.clear();
343
2.38k
  for (const SCEV *Expr : DimensionSizes) {
344
2.38k
    if (!Expr) {
345
1.84k
      DimensionSizesPw.push_back(nullptr);
346
1.84k
      continue;
347
1.84k
    }
348
541
    isl::pw_aff Size = S.getPwAffOnly(Expr);
349
541
    DimensionSizesPw.push_back(Size);
350
541
  }
351
1.93k
  return true;
352
1.93k
}
353
354
3.43k
std::string ScopArrayInfo::getName() const { return Id.get_name(); }
355
356
9.89k
int ScopArrayInfo::getElemSizeInBytes() const {
357
9.89k
  return DL.getTypeAllocSize(ElementType);
358
9.89k
}
359
360
5.33k
isl::id ScopArrayInfo::getBasePtrId() const { return Id; }
361
362
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
363
LLVM_DUMP_METHOD void ScopArrayInfo::dump() const { print(errs()); }
364
#endif
365
366
2.15k
void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const {
367
2.15k
  OS.indent(8) << *getElementType() << " " << getName();
368
2.15k
  unsigned u = 0;
369
2.15k
  // If this is a Fortran array, then we can print the outermost dimension
370
2.15k
  // as a isl_pw_aff even though there is no SCEV information.
371
2.15k
  bool IsOutermostSizeKnown = SizeAsPwAff && 
FAD1.07k
;
372
2.15k
373
2.15k
  if (!IsOutermostSizeKnown && 
getNumberOfDimensions() > 02.14k
&&
374
2.15k
      
!getDimensionSize(0)1.65k
) {
375
1.54k
    OS << "[*]";
376
1.54k
    u++;
377
1.54k
  }
378
2.79k
  for (; u < getNumberOfDimensions(); 
u++647
) {
379
647
    OS << "[";
380
647
381
647
    if (SizeAsPwAff) {
382
326
      isl::pw_aff Size = getDimensionSizePw(u);
383
326
      OS << " " << Size << " ";
384
326
    } else {
385
321
      OS << *getDimensionSize(u);
386
321
    }
387
647
388
647
    OS << "]";
389
647
  }
390
2.15k
391
2.15k
  OS << ";";
392
2.15k
393
2.15k
  if (BasePtrOriginSAI)
394
92
    OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]";
395
2.15k
396
2.15k
  OS << " // Element size " << getElemSizeInBytes() << "\n";
397
2.15k
}
398
399
const ScopArrayInfo *
400
0
ScopArrayInfo::getFromAccessFunction(isl::pw_multi_aff PMA) {
401
0
  isl::id Id = PMA.get_tuple_id(isl::dim::out);
402
0
  assert(!Id.is_null() && "Output dimension didn't have an ID");
403
0
  return getFromId(Id);
404
0
}
405
406
1.41k
const ScopArrayInfo *ScopArrayInfo::getFromId(isl::id Id) {
407
1.41k
  void *User = Id.get_user();
408
1.41k
  const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
409
1.41k
  return SAI;
410
1.41k
}
411
412
13
void MemoryAccess::wrapConstantDimensions() {
413
13
  auto *SAI = getScopArrayInfo();
414
13
  isl::space ArraySpace = SAI->getSpace();
415
13
  isl::ctx Ctx = ArraySpace.get_ctx();
416
13
  unsigned DimsArray = SAI->getNumberOfDimensions();
417
13
418
13
  isl::multi_aff DivModAff = isl::multi_aff::identity(
419
13
      ArraySpace.map_from_domain_and_range(ArraySpace));
420
13
  isl::local_space LArraySpace = isl::local_space(ArraySpace);
421
13
422
13
  // Begin with last dimension, to iteratively carry into higher dimensions.
423
30
  for (int i = DimsArray - 1; i > 0; 
i--17
) {
424
17
    auto *DimSize = SAI->getDimensionSize(i);
425
17
    auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize);
426
17
427
17
    // This transformation is not applicable to dimensions with dynamic size.
428
17
    if (!DimSizeCst)
429
0
      continue;
430
17
431
17
    // This transformation is not applicable to dimensions of size zero.
432
17
    if (DimSize->isZero())
433
0
      continue;
434
17
435
17
    isl::val DimSizeVal =
436
17
        valFromAPInt(Ctx.get(), DimSizeCst->getAPInt(), false);
437
17
    isl::aff Var = isl::aff::var_on_domain(LArraySpace, isl::dim::set, i);
438
17
    isl::aff PrevVar =
439
17
        isl::aff::var_on_domain(LArraySpace, isl::dim::set, i - 1);
440
17
441
17
    // Compute: index % size
442
17
    // Modulo must apply in the divide of the previous iteration, if any.
443
17
    isl::aff Modulo = Var.mod(DimSizeVal);
444
17
    Modulo = Modulo.pullback(DivModAff);
445
17
446
17
    // Compute: floor(index / size)
447
17
    isl::aff Divide = Var.div(isl::aff(LArraySpace, DimSizeVal));
448
17
    Divide = Divide.floor();
449
17
    Divide = Divide.add(PrevVar);
450
17
    Divide = Divide.pullback(DivModAff);
451
17
452
17
    // Apply Modulo and Divide.
453
17
    DivModAff = DivModAff.set_aff(i, Modulo);
454
17
    DivModAff = DivModAff.set_aff(i - 1, Divide);
455
17
  }
456
13
457
13
  // Apply all modulo/divides on the accesses.
458
13
  isl::map Relation = AccessRelation;
459
13
  Relation = Relation.apply_range(isl::map::from_multi_aff(DivModAff));
460
13
  Relation = Relation.detect_equalities();
461
13
  AccessRelation = Relation;
462
13
}
463
464
4.72k
void MemoryAccess::updateDimensionality() {
465
4.72k
  auto *SAI = getScopArrayInfo();
466
4.72k
  isl::space ArraySpace = SAI->getSpace();
467
4.72k
  isl::space AccessSpace = AccessRelation.get_space().range();
468
4.72k
  isl::ctx Ctx = ArraySpace.get_ctx();
469
4.72k
470
4.72k
  auto DimsArray = ArraySpace.dim(isl::dim::set);
471
4.72k
  auto DimsAccess = AccessSpace.dim(isl::dim::set);
472
4.72k
  auto DimsMissing = DimsArray - DimsAccess;
473
4.72k
474
4.72k
  auto *BB = getStatement()->getEntryBlock();
475
4.72k
  auto &DL = BB->getModule()->getDataLayout();
476
4.72k
  unsigned ArrayElemSize = SAI->getElemSizeInBytes();
477
4.72k
  unsigned ElemBytes = DL.getTypeAllocSize(getElementType());
478
4.72k
479
4.72k
  isl::map Map = isl::map::from_domain_and_range(
480
4.72k
      isl::set::universe(AccessSpace), isl::set::universe(ArraySpace));
481
4.72k
482
4.74k
  for (unsigned i = 0; i < DimsMissing; 
i++17
)
483
17
    Map = Map.fix_si(isl::dim::out, i, 0);
484
4.72k
485
8.66k
  for (unsigned i = DimsMissing; i < DimsArray; 
i++3.94k
)
486
3.94k
    Map = Map.equate(isl::dim::in, i - DimsMissing, isl::dim::out, i);
487
4.72k
488
4.72k
  AccessRelation = AccessRelation.apply_range(Map);
489
4.72k
490
4.72k
  // For the non delinearized arrays, divide the access function of the last
491
4.72k
  // subscript by the size of the elements in the array.
492
4.72k
  //
493
4.72k
  // A stride one array access in C expressed as A[i] is expressed in
494
4.72k
  // LLVM-IR as something like A[i * elementsize]. This hides the fact that
495
4.72k
  // two subsequent values of 'i' index two values that are stored next to
496
4.72k
  // each other in memory. By this division we make this characteristic
497
4.72k
  // obvious again. If the base pointer was accessed with offsets not divisible
498
4.72k
  // by the accesses element size, we will have chosen a smaller ArrayElemSize
499
4.72k
  // that divides the offsets of all accesses to this base pointer.
500
4.72k
  if (DimsAccess == 1) {
501
2.97k
    isl::val V = isl::val(Ctx, ArrayElemSize);
502
2.97k
    AccessRelation = AccessRelation.floordiv_val(V);
503
2.97k
  }
504
4.72k
505
4.72k
  // We currently do this only if we added at least one dimension, which means
506
4.72k
  // some dimension's indices have not been specified, an indicator that some
507
4.72k
  // index values have been added together.
508
4.72k
  // TODO: Investigate general usefulness; Effect on unit tests is to make index
509
4.72k
  // expressions more complicated.
510
4.72k
  if (DimsMissing)
511
13
    wrapConstantDimensions();
512
4.72k
513
4.72k
  if (!isAffine())
514
59
    computeBoundsOnAccessRelation(ArrayElemSize);
515
4.72k
516
4.72k
  // Introduce multi-element accesses in case the type loaded by this memory
517
4.72k
  // access is larger than the canonical element type of the array.
518
4.72k
  //
519
4.72k
  // An access ((float *)A)[i] to an array char *A is modeled as
520
4.72k
  // {[i] -> A[o] : 4 i <= o <= 4 i + 3
521
4.72k
  if (ElemBytes > ArrayElemSize) {
522
55
    assert(ElemBytes % ArrayElemSize == 0 &&
523
55
           "Loaded element size should be multiple of canonical element size");
524
55
    isl::map Map = isl::map::from_domain_and_range(
525
55
        isl::set::universe(ArraySpace), isl::set::universe(ArraySpace));
526
59
    for (unsigned i = 0; i < DimsArray - 1; 
i++4
)
527
4
      Map = Map.equate(isl::dim::in, i, isl::dim::out, i);
528
55
529
55
    isl::constraint C;
530
55
    isl::local_space LS;
531
55
532
55
    LS = isl::local_space(Map.get_space());
533
55
    int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes();
534
55
535
55
    C = isl::constraint::alloc_inequality(LS);
536
55
    C = C.set_constant_val(isl::val(Ctx, Num - 1));
537
55
    C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, 1);
538
55
    C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, -1);
539
55
    Map = Map.add_constraint(C);
540
55
541
55
    C = isl::constraint::alloc_inequality(LS);
542
55
    C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, -1);
543
55
    C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, 1);
544
55
    C = C.set_constant_val(isl::val(Ctx, 0));
545
55
    Map = Map.add_constraint(C);
546
55
    AccessRelation = AccessRelation.apply_range(Map);
547
55
  }
548
4.72k
}
549
550
const std::string
551
293
MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
552
293
  switch (RT) {
553
293
  case MemoryAccess::RT_NONE:
554
0
    llvm_unreachable("Requested a reduction operator string for a memory "
555
293
                     "access which isn't a reduction");
556
293
  case MemoryAccess::RT_ADD:
557
275
    return "+";
558
293
  case MemoryAccess::RT_MUL:
559
14
    return "*";
560
293
  case MemoryAccess::RT_BOR:
561
1
    return "|";
562
293
  case MemoryAccess::RT_BXOR:
563
2
    return "^";
564
293
  case MemoryAccess::RT_BAND:
565
1
    return "&";
566
0
  }
567
0
  llvm_unreachable("Unknown reduction type");
568
0
}
569
570
23.5k
const ScopArrayInfo *MemoryAccess::getOriginalScopArrayInfo() const {
571
23.5k
  isl::id ArrayId = getArrayId();
572
23.5k
  void *User = ArrayId.get_user();
573
23.5k
  const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
574
23.5k
  return SAI;
575
23.5k
}
576
577
3.08k
const ScopArrayInfo *MemoryAccess::getLatestScopArrayInfo() const {
578
3.08k
  isl::id ArrayId = getLatestArrayId();
579
3.08k
  void *User = ArrayId.get_user();
580
3.08k
  const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
581
3.08k
  return SAI;
582
3.08k
}
583
584
26.5k
isl::id MemoryAccess::getOriginalArrayId() const {
585
26.5k
  return AccessRelation.get_tuple_id(isl::dim::out);
586
26.5k
}
587
588
3.08k
isl::id MemoryAccess::getLatestArrayId() const {
589
3.08k
  if (!hasNewAccessRelation())
590
2.77k
    return getOriginalArrayId();
591
302
  return NewAccessRelation.get_tuple_id(isl::dim::out);
592
302
}
593
594
338
isl::map MemoryAccess::getAddressFunction() const {
595
338
  return getAccessRelation().lexmin();
596
338
}
597
598
isl::pw_multi_aff
599
230
MemoryAccess::applyScheduleToAccessRelation(isl::union_map USchedule) const {
600
230
  isl::map Schedule, ScheduledAccRel;
601
230
  isl::union_set UDomain;
602
230
603
230
  UDomain = getStatement()->getDomain();
604
230
  USchedule = USchedule.intersect_domain(UDomain);
605
230
  Schedule = isl::map::from_union_map(USchedule);
606
230
  ScheduledAccRel = getAddressFunction().apply_domain(Schedule);
607
230
  return isl::pw_multi_aff::from_map(ScheduledAccRel);
608
230
}
609
610
17.3k
isl::map MemoryAccess::getOriginalAccessRelation() const {
611
17.3k
  return AccessRelation;
612
17.3k
}
613
614
2.34k
std::string MemoryAccess::getOriginalAccessRelationStr() const {
615
2.34k
  return AccessRelation.to_str();
616
2.34k
}
617
618
4.63k
isl::space MemoryAccess::getOriginalAccessRelationSpace() const {
619
4.63k
  return AccessRelation.get_space();
620
4.63k
}
621
622
539
isl::map MemoryAccess::getNewAccessRelation() const {
623
539
  return NewAccessRelation;
624
539
}
625
626
434
std::string MemoryAccess::getNewAccessRelationStr() const {
627
434
  return NewAccessRelation.to_str();
628
434
}
629
630
0
std::string MemoryAccess::getAccessRelationStr() const {
631
0
  return getAccessRelation().to_str();
632
0
}
633
634
60
isl::basic_map MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
635
60
  isl::space Space = isl::space(Statement->getIslCtx(), 0, 1);
636
60
  Space = Space.align_params(Statement->getDomainSpace());
637
60
638
60
  return isl::basic_map::from_domain_and_range(
639
60
      isl::basic_set::universe(Statement->getDomainSpace()),
640
60
      isl::basic_set::universe(Space));
641
60
}
642
643
// Formalize no out-of-bound access assumption
644
//
645
// When delinearizing array accesses we optimistically assume that the
646
// delinearized accesses do not access out of bound locations (the subscript
647
// expression of each array evaluates for each statement instance that is
648
// executed to a value that is larger than zero and strictly smaller than the
649
// size of the corresponding dimension). The only exception is the outermost
650
// dimension for which we do not need to assume any upper bound.  At this point
651
// we formalize this assumption to ensure that at code generation time the
652
// relevant run-time checks can be generated.
653
//
654
// To find the set of constraints necessary to avoid out of bound accesses, we
655
// first build the set of data locations that are not within array bounds. We
656
// then apply the reverse access relation to obtain the set of iterations that
657
// may contain invalid accesses and reduce this set of iterations to the ones
658
// that are actually executed by intersecting them with the domain of the
659
// statement. If we now project out all loop dimensions, we obtain a set of
660
// parameters that may cause statement instances to be executed that may
661
// possibly yield out of bound memory accesses. The complement of these
662
// constraints is the set of constraints that needs to be assumed to ensure such
663
// statement instances are never executed.
664
4.72k
void MemoryAccess::assumeNoOutOfBound() {
665
4.72k
  if (PollyIgnoreInbounds)
666
93
    return;
667
4.63k
  auto *SAI = getScopArrayInfo();
668
4.63k
  isl::space Space = getOriginalAccessRelationSpace().range();
669
4.63k
  isl::set Outside = isl::set::empty(Space);
670
5.19k
  for (int i = 1, Size = Space.dim(isl::dim::set); i < Size; 
++i559
) {
671
559
    isl::local_space LS(Space);
672
559
    isl::pw_aff Var = isl::pw_aff::var_on_domain(LS, isl::dim::set, i);
673
559
    isl::pw_aff Zero = isl::pw_aff(LS);
674
559
675
559
    isl::set DimOutside = Var.lt_set(Zero);
676
559
    isl::pw_aff SizeE = SAI->getDimensionSizePw(i);
677
559
    SizeE = SizeE.add_dims(isl::dim::in, Space.dim(isl::dim::set));
678
559
    SizeE = SizeE.set_tuple_id(isl::dim::in, Space.get_tuple_id(isl::dim::set));
679
559
    DimOutside = DimOutside.unite(SizeE.le_set(Var));
680
559
681
559
    Outside = Outside.unite(DimOutside);
682
559
  }
683
4.63k
684
4.63k
  Outside = Outside.apply(getAccessRelation().reverse());
685
4.63k
  Outside = Outside.intersect(Statement->getDomain());
686
4.63k
  Outside = Outside.params();
687
4.63k
688
4.63k
  // Remove divs to avoid the construction of overly complicated assumptions.
689
4.63k
  // Doing so increases the set of parameter combinations that are assumed to
690
4.63k
  // not appear. This is always save, but may make the resulting run-time check
691
4.63k
  // bail out more often than strictly necessary.
692
4.63k
  Outside = Outside.remove_divs();
693
4.63k
  Outside = Outside.complement();
694
4.63k
  const auto &Loc = getAccessInstruction()
695
4.63k
                        ? 
getAccessInstruction()->getDebugLoc()4.28k
696
4.63k
                        : 
DebugLoc()348
;
697
4.63k
  if (!PollyPreciseInbounds)
698
4.61k
    Outside = Outside.gist_params(Statement->getDomain().params());
699
4.63k
  Statement->getParent()->recordAssumption(INBOUNDS, Outside, Loc,
700
4.63k
                                           AS_ASSUMPTION);
701
4.63k
}
702
703
24
void MemoryAccess::buildMemIntrinsicAccessRelation() {
704
24
  assert(isMemoryIntrinsic());
705
24
  assert(Subscripts.size() == 2 && Sizes.size() == 1);
706
24
707
24
  isl::pw_aff SubscriptPWA = getPwAff(Subscripts[0]);
708
24
  isl::map SubscriptMap = isl::map::from_pw_aff(SubscriptPWA);
709
24
710
24
  isl::map LengthMap;
711
24
  if (Subscripts[1] == nullptr) {
712
0
    LengthMap = isl::map::universe(SubscriptMap.get_space());
713
24
  } else {
714
24
    isl::pw_aff LengthPWA = getPwAff(Subscripts[1]);
715
24
    LengthMap = isl::map::from_pw_aff(LengthPWA);
716
24
    isl::space RangeSpace = LengthMap.get_space().range();
717
24
    LengthMap = LengthMap.apply_range(isl::map::lex_gt(RangeSpace));
718
24
  }
719
24
  LengthMap = LengthMap.lower_bound_si(isl::dim::out, 0, 0);
720
24
  LengthMap = LengthMap.align_params(SubscriptMap.get_space());
721
24
  SubscriptMap = SubscriptMap.align_params(LengthMap.get_space());
722
24
  LengthMap = LengthMap.sum(SubscriptMap);
723
24
  AccessRelation =
724
24
      LengthMap.set_tuple_id(isl::dim::in, getStatement()->getDomainId());
725
24
}
726
727
59
void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) {
728
59
  ScalarEvolution *SE = Statement->getParent()->getSE();
729
59
730
59
  auto MAI = MemAccInst(getAccessInstruction());
731
59
  if (isa<MemIntrinsic>(MAI))
732
0
    return;
733
59
734
59
  Value *Ptr = MAI.getPointerOperand();
735
59
  if (!Ptr || 
!SE->isSCEVable(Ptr->getType())37
)
736
22
    return;
737
37
738
37
  auto *PtrSCEV = SE->getSCEV(Ptr);
739
37
  if (isa<SCEVCouldNotCompute>(PtrSCEV))
740
0
    return;
741
37
742
37
  auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
743
37
  if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
744
37
    PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
745
37
746
37
  const ConstantRange &Range = SE->getSignedRange(PtrSCEV);
747
37
  if (Range.isFullSet())
748
0
    return;
749
37
750
37
  if (Range.isUpperWrapped() || 
Range.isSignWrappedSet()13
)
751
26
    return;
752
11
753
11
  bool isWrapping = Range.isSignWrappedSet();
754
11
755
11
  unsigned BW = Range.getBitWidth();
756
11
  const auto One = APInt(BW, 1);
757
11
  const auto LB = isWrapping ? 
Range.getLower()0
: Range.getSignedMin();
758
11
  const auto UB = isWrapping ? 
(Range.getUpper() - One)0
: Range.getSignedMax();
759
11
760
11
  auto Min = LB.sdiv(APInt(BW, ElementSize));
761
11
  auto Max = UB.sdiv(APInt(BW, ElementSize)) + One;
762
11
763
11
  assert(Min.sle(Max) && "Minimum expected to be less or equal than max");
764
11
765
11
  isl::map Relation = AccessRelation;
766
11
  isl::set AccessRange = Relation.range();
767
11
  AccessRange = addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0,
768
11
                                    isl::dim::set);
769
11
  AccessRelation = Relation.intersect_range(AccessRange);
770
11
}
771
772
4.72k
void MemoryAccess::foldAccessRelation() {
773
4.72k
  if (Sizes.size() < 2 || 
isa<SCEVConstant>(Sizes[1])427
)
774
4.54k
    return;
775
181
776
181
  int Size = Subscripts.size();
777
181
778
181
  isl::map NewAccessRelation = AccessRelation;
779
181
780
458
  for (int i = Size - 2; i >= 0; 
--i277
) {
781
277
    isl::space Space;
782
277
    isl::map MapOne, MapTwo;
783
277
    isl::pw_aff DimSize = getPwAff(Sizes[i + 1]);
784
277
785
277
    isl::space SpaceSize = DimSize.get_space();
786
277
    isl::id ParamId = SpaceSize.get_dim_id(isl::dim::param, 0);
787
277
788
277
    Space = AccessRelation.get_space();
789
277
    Space = Space.range().map_from_set();
790
277
    Space = Space.align_params(SpaceSize);
791
277
792
277
    int ParamLocation = Space.find_dim_by_id(isl::dim::param, ParamId);
793
277
794
277
    MapOne = isl::map::universe(Space);
795
1.05k
    for (int j = 0; j < Size; 
++j782
)
796
782
      MapOne = MapOne.equate(isl::dim::in, j, isl::dim::out, j);
797
277
    MapOne = MapOne.lower_bound_si(isl::dim::in, i + 1, 0);
798
277
799
277
    MapTwo = isl::map::universe(Space);
800
1.05k
    for (int j = 0; j < Size; 
++j782
)
801
782
      if (j < i || 
j > i + 1668
)
802
228
        MapTwo = MapTwo.equate(isl::dim::in, j, isl::dim::out, j);
803
277
804
277
    isl::local_space LS(Space);
805
277
    isl::constraint C;
806
277
    C = isl::constraint::alloc_equality(LS);
807
277
    C = C.set_constant_si(-1);
808
277
    C = C.set_coefficient_si(isl::dim::in, i, 1);
809
277
    C = C.set_coefficient_si(isl::dim::out, i, -1);
810
277
    MapTwo = MapTwo.add_constraint(C);
811
277
    C = isl::constraint::alloc_equality(LS);
812
277
    C = C.set_coefficient_si(isl::dim::in, i + 1, 1);
813
277
    C = C.set_coefficient_si(isl::dim::out, i + 1, -1);
814
277
    C = C.set_coefficient_si(isl::dim::param, ParamLocation, 1);
815
277
    MapTwo = MapTwo.add_constraint(C);
816
277
    MapTwo = MapTwo.upper_bound_si(isl::dim::in, i + 1, -1);
817
277
818
277
    MapOne = MapOne.unite(MapTwo);
819
277
    NewAccessRelation = NewAccessRelation.apply_range(MapOne);
820
277
  }
821
181
822
181
  isl::id BaseAddrId = getScopArrayInfo()->getBasePtrId();
823
181
  isl::space Space = Statement->getDomainSpace();
824
181
  NewAccessRelation = NewAccessRelation.set_tuple_id(
825
181
      isl::dim::in, Space.get_tuple_id(isl::dim::set));
826
181
  NewAccessRelation = NewAccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
827
181
  NewAccessRelation = NewAccessRelation.gist_domain(Statement->getDomain());
828
181
829
181
  // Access dimension folding might in certain cases increase the number of
830
181
  // disjuncts in the memory access, which can possibly complicate the generated
831
181
  // run-time checks and can lead to costly compilation.
832
181
  if (!PollyPreciseFoldAccesses &&
833
181
      
NewAccessRelation.n_basic_map() > AccessRelation.n_basic_map()174
) {
834
174
  } else {
835
174
    AccessRelation = NewAccessRelation;
836
174
  }
837
181
}
838
839
4.77k
void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) {
840
4.77k
  assert(AccessRelation.is_null() && "AccessRelation already built");
841
4.77k
842
4.77k
  // Initialize the invalid domain which describes all iterations for which the
843
4.77k
  // access relation is not modeled correctly.
844
4.77k
  isl::set StmtInvalidDomain = getStatement()->getInvalidDomain();
845
4.77k
  InvalidDomain = isl::set::empty(StmtInvalidDomain.get_space());
846
4.77k
847
4.77k
  isl::ctx Ctx = Id.get_ctx();
848
4.77k
  isl::id BaseAddrId = SAI->getBasePtrId();
849
4.77k
850
4.77k
  if (getAccessInstruction() && 
isa<MemIntrinsic>(getAccessInstruction())4.42k
) {
851
24
    buildMemIntrinsicAccessRelation();
852
24
    AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
853
24
    return;
854
24
  }
855
4.75k
856
4.75k
  if (!isAffine()) {
857
60
    // We overapproximate non-affine accesses with a possible access to the
858
60
    // whole array. For read accesses it does not make a difference, if an
859
60
    // access must or may happen. However, for write accesses it is important to
860
60
    // differentiate between writes that must happen and writes that may happen.
861
60
    if (AccessRelation.is_null())
862
60
      AccessRelation = createBasicAccessMap(Statement);
863
60
864
60
    AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
865
60
    return;
866
60
  }
867
4.69k
868
4.69k
  isl::space Space = isl::space(Ctx, 0, Statement->getNumIterators(), 0);
869
4.69k
  AccessRelation = isl::map::universe(Space);
870
4.69k
871
8.58k
  for (int i = 0, Size = Subscripts.size(); i < Size; 
++i3.89k
) {
872
3.89k
    isl::pw_aff Affine = getPwAff(Subscripts[i]);
873
3.89k
    isl::map SubscriptMap = isl::map::from_pw_aff(Affine);
874
3.89k
    AccessRelation = AccessRelation.flat_range_product(SubscriptMap);
875
3.89k
  }
876
4.69k
877
4.69k
  Space = Statement->getDomainSpace();
878
4.69k
  AccessRelation = AccessRelation.set_tuple_id(
879
4.69k
      isl::dim::in, Space.get_tuple_id(isl::dim::set));
880
4.69k
  AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
881
4.69k
882
4.69k
  AccessRelation = AccessRelation.gist_domain(Statement->getDomain());
883
4.69k
}
884
885
MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
886
                           AccessType AccType, Value *BaseAddress,
887
                           Type *ElementType, bool Affine,
888
                           ArrayRef<const SCEV *> Subscripts,
889
                           ArrayRef<const SCEV *> Sizes, Value *AccessValue,
890
                           MemoryKind Kind)
891
    : Kind(Kind), AccType(AccType), Statement(Stmt), InvalidDomain(nullptr),
892
      BaseAddr(BaseAddress), ElementType(ElementType),
893
      Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst),
894
      AccessValue(AccessValue), IsAffine(Affine),
895
      Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(nullptr),
896
5.10k
      NewAccessRelation(nullptr), FAD(nullptr) {
897
5.10k
  static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
898
5.10k
  const std::string Access = TypeStrings[AccType] + utostr(Stmt->size());
899
5.10k
900
5.10k
  std::string IdName = Stmt->getBaseName() + Access;
901
5.10k
  Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this);
902
5.10k
}
903
904
MemoryAccess::MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel)
905
    : Kind(MemoryKind::Array), AccType(AccType), Statement(Stmt),
906
      InvalidDomain(nullptr), AccessRelation(nullptr),
907
48
      NewAccessRelation(AccRel), FAD(nullptr) {
908
48
  isl::id ArrayInfoId = NewAccessRelation.get_tuple_id(isl::dim::out);
909
48
  auto *SAI = ScopArrayInfo::getFromId(ArrayInfoId);
910
48
  Sizes.push_back(nullptr);
911
120
  for (unsigned i = 1; i < SAI->getNumberOfDimensions(); 
i++72
)
912
72
    Sizes.push_back(SAI->getDimensionSize(i));
913
48
  ElementType = SAI->getElementType();
914
48
  BaseAddr = SAI->getBasePtr();
915
48
  static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
916
48
  const std::string Access = TypeStrings[AccType] + utostr(Stmt->size());
917
48
918
48
  std::string IdName = Stmt->getBaseName() + Access;
919
48
  Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this);
920
48
}
921
922
5.08k
MemoryAccess::~MemoryAccess() = default;
923
924
4.72k
void MemoryAccess::realignParams() {
925
4.72k
  isl::set Ctx = Statement->getParent()->getContext();
926
4.72k
  InvalidDomain = InvalidDomain.gist_params(Ctx);
927
4.72k
  AccessRelation = AccessRelation.gist_params(Ctx);
928
4.72k
}
929
930
0
const std::string MemoryAccess::getReductionOperatorStr() const {
931
0
  return MemoryAccess::getReductionOperatorStr(getReductionType());
932
0
}
933
934
1.90k
isl::id MemoryAccess::getId() const { return Id; }
935
936
raw_ostream &polly::operator<<(raw_ostream &OS,
937
2.34k
                               MemoryAccess::ReductionType RT) {
938
2.34k
  if (RT == MemoryAccess::RT_NONE)
939
2.07k
    OS << "NONE";
940
264
  else
941
264
    OS << MemoryAccess::getReductionOperatorStr(RT);
942
2.34k
  return OS;
943
2.34k
}
944
945
10
void MemoryAccess::setFortranArrayDescriptor(Value *FAD) { this->FAD = FAD; }
946
947
2.34k
void MemoryAccess::print(raw_ostream &OS) const {
948
2.34k
  switch (AccType) {
949
2.34k
  case READ:
950
1.07k
    OS.indent(12) << "ReadAccess :=\t";
951
1.07k
    break;
952
2.34k
  case MUST_WRITE:
953
1.22k
    OS.indent(12) << "MustWriteAccess :=\t";
954
1.22k
    break;
955
2.34k
  case MAY_WRITE:
956
43
    OS.indent(12) << "MayWriteAccess :=\t";
957
43
    break;
958
2.34k
  }
959
2.34k
960
2.34k
  OS << "[Reduction Type: " << getReductionType() << "] ";
961
2.34k
962
2.34k
  if (FAD) {
963
8
    OS << "[Fortran array descriptor: " << FAD->getName();
964
8
    OS << "] ";
965
8
  };
966
2.34k
967
2.34k
  OS << "[Scalar: " << isScalarKind() << "]\n";
968
2.34k
  OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
969
2.34k
  if (hasNewAccessRelation())
970
434
    OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n";
971
2.34k
}
972
973
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
974
LLVM_DUMP_METHOD void MemoryAccess::dump() const { print(errs()); }
975
#endif
976
977
4.21k
isl::pw_aff MemoryAccess::getPwAff(const SCEV *E) {
978
4.21k
  auto *Stmt = getStatement();
979
4.21k
  PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock());
980
4.21k
  isl::set StmtDom = getStatement()->getDomain();
981
4.21k
  StmtDom = StmtDom.reset_tuple_id();
982
4.21k
  isl::set NewInvalidDom = StmtDom.intersect(PWAC.second);
983
4.21k
  InvalidDomain = InvalidDomain.unite(NewInvalidDom);
984
4.21k
  return PWAC.first;
985
4.21k
}
986
987
// Create a map in the size of the provided set domain, that maps from the
988
// one element of the provided set domain to another element of the provided
989
// set domain.
990
// The mapping is limited to all points that are equal in all but the last
991
// dimension and for which the last dimension of the input is strict smaller
992
// than the last dimension of the output.
993
//
994
//   getEqualAndLarger(set[i0, i1, ..., iX]):
995
//
996
//   set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
997
//     : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
998
//
999
47
static isl::map getEqualAndLarger(isl::space SetDomain) {
1000
47
  isl::space Space = SetDomain.map_from_set();
1001
47
  isl::map Map = isl::map::universe(Space);
1002
47
  unsigned lastDimension = Map.dim(isl::dim::in) - 1;
1003
47
1004
47
  // Set all but the last dimension to be equal for the input and output
1005
47
  //
1006
47
  //   input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
1007
47
  //     : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
1008
75
  for (unsigned i = 0; i < lastDimension; 
++i28
)
1009
28
    Map = Map.equate(isl::dim::in, i, isl::dim::out, i);
1010
47
1011
47
  // Set the last dimension of the input to be strict smaller than the
1012
47
  // last dimension of the output.
1013
47
  //
1014
47
  //   input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
1015
47
  Map = Map.order_lt(isl::dim::in, lastDimension, isl::dim::out, lastDimension);
1016
47
  return Map;
1017
47
}
1018
1019
47
isl::set MemoryAccess::getStride(isl::map Schedule) const {
1020
47
  isl::map AccessRelation = getAccessRelation();
1021
47
  isl::space Space = Schedule.get_space().range();
1022
47
  isl::map NextScatt = getEqualAndLarger(Space);
1023
47
1024
47
  Schedule = Schedule.reverse();
1025
47
  NextScatt = NextScatt.lexmin();
1026
47
1027
47
  NextScatt = NextScatt.apply_range(Schedule);
1028
47
  NextScatt = NextScatt.apply_range(AccessRelation);
1029
47
  NextScatt = NextScatt.apply_domain(Schedule);
1030
47
  NextScatt = NextScatt.apply_domain(AccessRelation);
1031
47
1032
47
  isl::set Deltas = NextScatt.deltas();
1033
47
  return Deltas;
1034
47
}
1035
1036
47
bool MemoryAccess::isStrideX(isl::map Schedule, int StrideWidth) const {
1037
47
  isl::set Stride, StrideX;
1038
47
  bool IsStrideX;
1039
47
1040
47
  Stride = getStride(Schedule);
1041
47
  StrideX = isl::set::universe(Stride.get_space());
1042
57
  for (unsigned i = 0; i < StrideX.dim(isl::dim::set) - 1; 
i++10
)
1043
10
    StrideX = StrideX.fix_si(isl::dim::set, i, 0);
1044
47
  StrideX = StrideX.fix_si(isl::dim::set, StrideX.dim(isl::dim::set) - 1,
1045
47
                           StrideWidth);
1046
47
  IsStrideX = Stride.is_subset(StrideX);
1047
47
1048
47
  return IsStrideX;
1049
47
}
1050
1051
15
bool MemoryAccess::isStrideZero(isl::map Schedule) const {
1052
15
  return isStrideX(Schedule, 0);
1053
15
}
1054
1055
28
bool MemoryAccess::isStrideOne(isl::map Schedule) const {
1056
28
  return isStrideX(Schedule, 1);
1057
28
}
1058
1059
21
void MemoryAccess::setAccessRelation(isl::map NewAccess) {
1060
21
  AccessRelation = NewAccess;
1061
21
}
1062
1063
520
void MemoryAccess::setNewAccessRelation(isl::map NewAccess) {
1064
520
  assert(NewAccess);
1065
520
1066
#ifndef NDEBUG
1067
  // Check domain space compatibility.
1068
  isl::space NewSpace = NewAccess.get_space();
1069
  isl::space NewDomainSpace = NewSpace.domain();
1070
  isl::space OriginalDomainSpace = getStatement()->getDomainSpace();
1071
  assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace));
1072
1073
  // Reads must be executed unconditionally. Writes might be executed in a
1074
  // subdomain only.
1075
  if (isRead()) {
1076
    // Check whether there is an access for every statement instance.
1077
    isl::set StmtDomain = getStatement()->getDomain();
1078
    StmtDomain =
1079
        StmtDomain.intersect_params(getStatement()->getParent()->getContext());
1080
    isl::set NewDomain = NewAccess.domain();
1081
    assert(StmtDomain.is_subset(NewDomain) &&
1082
           "Partial READ accesses not supported");
1083
  }
1084
1085
  isl::space NewAccessSpace = NewAccess.get_space();
1086
  assert(NewAccessSpace.has_tuple_id(isl::dim::set) &&
1087
         "Must specify the array that is accessed");
1088
  isl::id NewArrayId = NewAccessSpace.get_tuple_id(isl::dim::set);
1089
  auto *SAI = static_cast<ScopArrayInfo *>(NewArrayId.get_user());
1090
  assert(SAI && "Must set a ScopArrayInfo");
1091
1092
  if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) {
1093
    InvariantEquivClassTy *EqClass =
1094
        getStatement()->getParent()->lookupInvariantEquivClass(
1095
            SAI->getBasePtr());
1096
    assert(EqClass &&
1097
           "Access functions to indirect arrays must have an invariant and "
1098
           "hoisted base pointer");
1099
  }
1100
1101
  // Check whether access dimensions correspond to number of dimensions of the
1102
  // accesses array.
1103
  auto Dims = SAI->getNumberOfDimensions();
1104
  assert(NewAccessSpace.dim(isl::dim::set) == Dims &&
1105
         "Access dims must match array dims");
1106
#endif
1107
1108
520
  NewAccess = NewAccess.gist_domain(getStatement()->getDomain());
1109
520
  NewAccessRelation = NewAccess;
1110
520
}
1111
1112
27
bool MemoryAccess::isLatestPartialAccess() const {
1113
27
  isl::set StmtDom = getStatement()->getDomain();
1114
27
  isl::set AccDom = getLatestAccessRelation().domain();
1115
27
1116
27
  return !StmtDom.is_subset(AccDom);
1117
27
}
1118
1119
//===----------------------------------------------------------------------===//
1120
1121
1.25k
isl::map ScopStmt::getSchedule() const {
1122
1.25k
  isl::set Domain = getDomain();
1123
1.25k
  if (Domain.is_empty())
1124
4
    return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace())));
1125
1.25k
  auto Schedule = getParent()->getSchedule();
1126
1.25k
  if (!Schedule)
1127
0
    return nullptr;
1128
1.25k
  Schedule = Schedule.intersect_domain(isl::union_set(Domain));
1129
1.25k
  if (Schedule.is_empty())
1130
0
    return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace())));
1131
1.25k
  isl::map M = M.from_union_map(Schedule);
1132
1.25k
  M = M.coalesce();
1133
1.25k
  M = M.gist_domain(Domain);
1134
1.25k
  M = M.coalesce();
1135
1.25k
  return M;
1136
1.25k
}
1137
1138
8
void ScopStmt::restrictDomain(isl::set NewDomain) {
1139
8
  assert(NewDomain.is_subset(Domain) &&
1140
8
         "New domain is not a subset of old domain!");
1141
8
  Domain = NewDomain;
1142
8
}
1143
1144
5.15k
void ScopStmt::addAccess(MemoryAccess *Access, bool Prepend) {
1145
5.15k
  Instruction *AccessInst = Access->getAccessInstruction();
1146
5.15k
1147
5.15k
  if (Access->isArrayKind()) {
1148
3.74k
    MemoryAccessList &MAL = InstructionToAccess[AccessInst];
1149
3.74k
    MAL.emplace_front(Access);
1150
3.74k
  } else 
if (1.40k
Access->isValueKind()1.40k
&&
Access->isWrite()708
) {
1151
343
    Instruction *AccessVal = cast<Instruction>(Access->getAccessValue());
1152
343
    assert(!ValueWrites.lookup(AccessVal));
1153
343
1154
343
    ValueWrites[AccessVal] = Access;
1155
1.06k
  } else if (Access->isValueKind() && 
Access->isRead()365
) {
1156
365
    Value *AccessVal = Access->getAccessValue();
1157
365
    assert(!ValueReads.lookup(AccessVal));
1158
365
1159
365
    ValueReads[AccessVal] = Access;
1160
699
  } else if (Access->isAnyPHIKind() && Access->isWrite()) {
1161
461
    PHINode *PHI = cast<PHINode>(Access->getAccessValue());
1162
461
    assert(!PHIWrites.lookup(PHI));
1163
461
1164
461
    PHIWrites[PHI] = Access;
1165
461
  } else 
if (238
Access->isAnyPHIKind()238
&&
Access->isRead()238
) {
1166
238
    PHINode *PHI = cast<PHINode>(Access->getAccessValue());
1167
238
    assert(!PHIReads.lookup(PHI));
1168
238
1169
238
    PHIReads[PHI] = Access;
1170
238
  }
1171
5.15k
1172
5.15k
  if (Prepend) {
1173
16
    MemAccs.insert(MemAccs.begin(), Access);
1174
16
    return;
1175
16
  }
1176
5.13k
  MemAccs.push_back(Access);
1177
5.13k
}
1178
1179
2.31k
void ScopStmt::realignParams() {
1180
2.31k
  for (MemoryAccess *MA : *this)
1181
4.72k
    MA->realignParams();
1182
2.31k
1183
2.31k
  isl::set Ctx = Parent.getContext();
1184
2.31k
  InvalidDomain = InvalidDomain.gist_params(Ctx);
1185
2.31k
  Domain = Domain.gist_params(Ctx);
1186
2.31k
}
1187
1188
/// Add @p BSet to set @p BoundedParts if @p BSet is bounded.
1189
1.69k
static isl::set collectBoundedParts(isl::set S) {
1190
1.69k
  isl::set BoundedParts = isl::set::empty(S.get_space());
1191
1.69k
  for (isl::basic_set BSet : S.get_basic_set_list())
1192
2.33k
    if (BSet.is_bounded())
1193
2.09k
      BoundedParts = BoundedParts.unite(isl::set(BSet));
1194
1.69k
  return BoundedParts;
1195
1.69k
}
1196
1197
/// Compute the (un)bounded parts of @p S wrt. to dimension @p Dim.
1198
///
1199
/// @returns A separation of @p S into first an unbounded then a bounded subset,
1200
///          both with regards to the dimension @p Dim.
1201
static std::pair<isl::set, isl::set> partitionSetParts(isl::set S,
1202
1.69k
                                                       unsigned Dim) {
1203
3.97k
  for (unsigned u = 0, e = S.n_dim(); u < e; 
u++2.27k
)
1204
2.27k
    S = S.lower_bound_si(isl::dim::set, u, 0);
1205
1.69k
1206
1.69k
  unsigned NumDimsS = S.n_dim();
1207
1.69k
  isl::set OnlyDimS = S;
1208
1.69k
1209
1.69k
  // Remove dimensions that are greater than Dim as they are not interesting.
1210
1.69k
  assert(NumDimsS >= Dim + 1);
1211
1.69k
  OnlyDimS = OnlyDimS.project_out(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
1212
1.69k
1213
1.69k
  // Create artificial parametric upper bounds for dimensions smaller than Dim
1214
1.69k
  // as we are not interested in them.
1215
1.69k
  OnlyDimS = OnlyDimS.insert_dims(isl::dim::param, 0, Dim);
1216
1.69k
1217
2.27k
  for (unsigned u = 0; u < Dim; 
u++572
) {
1218
572
    isl::constraint C = isl::constraint::alloc_inequality(
1219
572
        isl::local_space(OnlyDimS.get_space()));
1220
572
    C = C.set_coefficient_si(isl::dim::param, u, 1);
1221
572
    C = C.set_coefficient_si(isl::dim::set, u, -1);
1222
572
    OnlyDimS = OnlyDimS.add_constraint(C);
1223
572
  }
1224
1.69k
1225
1.69k
  // Collect all bounded parts of OnlyDimS.
1226
1.69k
  isl::set BoundedParts = collectBoundedParts(OnlyDimS);
1227
1.69k
1228
1.69k
  // Create the dimensions greater than Dim again.
1229
1.69k
  BoundedParts =
1230
1.69k
      BoundedParts.insert_dims(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
1231
1.69k
1232
1.69k
  // Remove the artificial upper bound parameters again.
1233
1.69k
  BoundedParts = BoundedParts.remove_dims(isl::dim::param, 0, Dim);
1234
1.69k
1235
1.69k
  isl::set UnboundedParts = S.subtract(BoundedParts);
1236
1.69k
  return std::make_pair(UnboundedParts, BoundedParts);
1237
1.69k
}
1238
1239
/// Create the conditions under which @p L @p Pred @p R is true.
1240
static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L,
1241
2.73k
                                  isl::pw_aff R) {
1242
2.73k
  switch (Pred) {
1243
2.73k
  case ICmpInst::ICMP_EQ:
1244
741
    return L.eq_set(R);
1245
2.73k
  case ICmpInst::ICMP_NE:
1246
1.08k
    return L.ne_set(R);
1247
2.73k
  case ICmpInst::ICMP_SLT:
1248
726
    return L.lt_set(R);
1249
2.73k
  case ICmpInst::ICMP_SLE:
1250
58
    return L.le_set(R);
1251
2.73k
  case ICmpInst::ICMP_SGT:
1252
117
    return L.gt_set(R);
1253
2.73k
  case ICmpInst::ICMP_SGE:
1254
13
    return L.ge_set(R);
1255
2.73k
  case ICmpInst::ICMP_ULT:
1256
0
    return L.lt_set(R);
1257
2.73k
  case ICmpInst::ICMP_UGT:
1258
0
    return L.gt_set(R);
1259
2.73k
  case ICmpInst::ICMP_ULE:
1260
0
    return L.le_set(R);
1261
2.73k
  case ICmpInst::ICMP_UGE:
1262
0
    return L.ge_set(R);
1263
2.73k
  default:
1264
0
    llvm_unreachable("Non integer predicate not supported");
1265
2.73k
  }
1266
2.73k
}
1267
1268
/// Compute the isl representation for the SCEV @p E in this BB.
1269
///
1270
/// @param S                The Scop in which @p BB resides in.
1271
/// @param BB               The BB for which isl representation is to be
1272
/// computed.
1273
/// @param InvalidDomainMap A map of BB to their invalid domains.
1274
/// @param E                The SCEV that should be translated.
1275
/// @param NonNegative      Flag to indicate the @p E has to be non-negative.
1276
///
1277
/// Note that this function will also adjust the invalid context accordingly.
1278
1279
__isl_give isl_pw_aff *
1280
getPwAff(Scop &S, BasicBlock *BB,
1281
         DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, const SCEV *E,
1282
5.52k
         bool NonNegative = false) {
1283
5.52k
  PWACtx PWAC = S.getPwAff(E, BB, NonNegative);
1284
5.52k
  InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
1285
5.52k
  return PWAC.first.release();
1286
5.52k
}
1287
1288
/// Build the conditions sets for the switch @p SI in the @p Domain.
1289
///
1290
/// This will fill @p ConditionSets with the conditions under which control
1291
/// will be moved from @p SI to its successors. Hence, @p ConditionSets will
1292
/// have as many elements as @p SI has successors.
1293
bool buildConditionSets(Scop &S, BasicBlock *BB, SwitchInst *SI, Loop *L,
1294
                        __isl_keep isl_set *Domain,
1295
                        DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1296
17
                        SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1297
17
  Value *Condition = getConditionFromTerminator(SI);
1298
17
  assert(Condition && "No condition for switch");
1299
17
1300
17
  ScalarEvolution &SE = *S.getSE();
1301
17
  isl_pw_aff *LHS, *RHS;
1302
17
  LHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEVAtScope(Condition, L));
1303
17
1304
17
  unsigned NumSuccessors = SI->getNumSuccessors();
1305
17
  ConditionSets.resize(NumSuccessors);
1306
54
  for (auto &Case : SI->cases()) {
1307
54
    unsigned Idx = Case.getSuccessorIndex();
1308
54
    ConstantInt *CaseValue = Case.getCaseValue();
1309
54
1310
54
    RHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEV(CaseValue));
1311
54
    isl_set *CaseConditionSet =
1312
54
        buildConditionSet(ICmpInst::ICMP_EQ, isl::manage_copy(LHS),
1313
54
                          isl::manage(RHS))
1314
54
            .release();
1315
54
    ConditionSets[Idx] = isl_set_coalesce(
1316
54
        isl_set_intersect(CaseConditionSet, isl_set_copy(Domain)));
1317
54
  }
1318
17
1319
17
  assert(ConditionSets[0] == nullptr && "Default condition set was set");
1320
17
  isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]);
1321
54
  for (unsigned u = 2; u < NumSuccessors; 
u++37
)
1322
37
    ConditionSetUnion =
1323
37
        isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u]));
1324
17
  ConditionSets[0] = isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion);
1325
17
1326
17
  isl_pw_aff_free(LHS);
1327
17
1328
17
  return true;
1329
17
}
1330
1331
/// Build condition sets for unsigned ICmpInst(s).
1332
/// Special handling is required for unsigned operands to ensure that if
1333
/// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst
1334
/// it should wrap around.
1335
///
1336
/// @param IsStrictUpperBound holds information on the predicate relation
1337
/// between TestVal and UpperBound, i.e,
1338
/// TestVal < UpperBound  OR  TestVal <= UpperBound
1339
__isl_give isl_set *
1340
buildUnsignedConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
1341
                           __isl_keep isl_set *Domain, const SCEV *SCEV_TestVal,
1342
                           const SCEV *SCEV_UpperBound,
1343
                           DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1344
43
                           bool IsStrictUpperBound) {
1345
43
  // Do not take NonNeg assumption on TestVal
1346
43
  // as it might have MSB (Sign bit) set.
1347
43
  isl_pw_aff *TestVal = getPwAff(S, BB, InvalidDomainMap, SCEV_TestVal, false);
1348
43
  // Take NonNeg assumption on UpperBound.
1349
43
  isl_pw_aff *UpperBound =
1350
43
      getPwAff(S, BB, InvalidDomainMap, SCEV_UpperBound, true);
1351
43
1352
43
  // 0 <= TestVal
1353
43
  isl_set *First =
1354
43
      isl_pw_aff_le_set(isl_pw_aff_zero_on_domain(isl_local_space_from_space(
1355
43
                            isl_pw_aff_get_domain_space(TestVal))),
1356
43
                        isl_pw_aff_copy(TestVal));
1357
43
1358
43
  isl_set *Second;
1359
43
  if (IsStrictUpperBound)
1360
35
    // TestVal < UpperBound
1361
35
    Second = isl_pw_aff_lt_set(TestVal, UpperBound);
1362
8
  else
1363
8
    // TestVal <= UpperBound
1364
8
    Second = isl_pw_aff_le_set(TestVal, UpperBound);
1365
43
1366
43
  isl_set *ConsequenceCondSet = isl_set_intersect(First, Second);
1367
43
  return ConsequenceCondSet;
1368
43
}
1369
1370
/// Build the conditions sets for the branch condition @p Condition in
1371
/// the @p Domain.
1372
///
1373
/// This will fill @p ConditionSets with the conditions under which control
1374
/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
1375
/// have as many elements as @p TI has successors. If @p TI is nullptr the
1376
/// context under which @p Condition is true/false will be returned as the
1377
/// new elements of @p ConditionSets.
1378
bool buildConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
1379
                        Instruction *TI, Loop *L, __isl_keep isl_set *Domain,
1380
                        DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1381
2.97k
                        SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1382
2.97k
  ScalarEvolution &SE = *S.getSE();
1383
2.97k
  isl_set *ConsequenceCondSet = nullptr;
1384
2.97k
1385
2.97k
  if (auto Load = dyn_cast<LoadInst>(Condition)) {
1386
1
    const SCEV *LHSSCEV = SE.getSCEVAtScope(Load, L);
1387
1
    const SCEV *RHSSCEV = SE.getZero(LHSSCEV->getType());
1388
1
    bool NonNeg = false;
1389
1
    isl_pw_aff *LHS = getPwAff(S, BB, InvalidDomainMap, LHSSCEV, NonNeg);
1390
1
    isl_pw_aff *RHS = getPwAff(S, BB, InvalidDomainMap, RHSSCEV, NonNeg);
1391
1
    ConsequenceCondSet = buildConditionSet(ICmpInst::ICMP_SLE, isl::manage(LHS),
1392
1
                                           isl::manage(RHS))
1393
1
                             .release();
1394
2.97k
  } else if (auto *PHI = dyn_cast<PHINode>(Condition)) {
1395
1
    auto *Unique = dyn_cast<ConstantInt>(
1396
1
        getUniqueNonErrorValue(PHI, &S.getRegion(), *S.getLI(), *S.getDT()));
1397
1
1398
1
    if (Unique->isZero())
1399
0
      ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
1400
1
    else
1401
1
      ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
1402
2.97k
  } else if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
1403
201
    if (CCond->isZero())
1404
167
      ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
1405
34
    else
1406
34
      ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
1407
2.76k
  } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
1408
42
    auto Opcode = BinOp->getOpcode();
1409
42
    assert(Opcode == Instruction::And || Opcode == Instruction::Or);
1410
42
1411
42
    bool Valid = buildConditionSets(S, BB, BinOp->getOperand(0), TI, L, Domain,
1412
42
                                    InvalidDomainMap, ConditionSets) &&
1413
42
                 buildConditionSets(S, BB, BinOp->getOperand(1), TI, L, Domain,
1414
23
                                    InvalidDomainMap, ConditionSets);
1415
42
    if (!Valid) {
1416
22
      while (!ConditionSets.empty())
1417
2
        isl_set_free(ConditionSets.pop_back_val());
1418
20
      return false;
1419
20
    }
1420
22
1421
22
    isl_set_free(ConditionSets.pop_back_val());
1422
22
    isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
1423
22
    isl_set_free(ConditionSets.pop_back_val());
1424
22
    isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
1425
22
1426
22
    if (Opcode == Instruction::And)
1427
10
      ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1);
1428
12
    else
1429
12
      ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1);
1430
2.72k
  } else {
1431
2.72k
    auto *ICond = dyn_cast<ICmpInst>(Condition);
1432
2.72k
    assert(ICond &&
1433
2.72k
           "Condition of exiting branch was neither constant nor ICmp!");
1434
2.72k
1435
2.72k
    LoopInfo &LI = *S.getLI();
1436
2.72k
    DominatorTree &DT = *S.getDT();
1437
2.72k
    Region &R = S.getRegion();
1438
2.72k
1439
2.72k
    isl_pw_aff *LHS, *RHS;
1440
2.72k
    // For unsigned comparisons we assumed the signed bit of neither operand
1441
2.72k
    // to be set. The comparison is equal to a signed comparison under this
1442
2.72k
    // assumption.
1443
2.72k
    bool NonNeg = ICond->isUnsigned();
1444
2.72k
    const SCEV *LeftOperand = SE.getSCEVAtScope(ICond->getOperand(0), L),
1445
2.72k
               *RightOperand = SE.getSCEVAtScope(ICond->getOperand(1), L);
1446
2.72k
1447
2.72k
    LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, LI, DT);
1448
2.72k
    RightOperand = tryForwardThroughPHI(RightOperand, R, SE, LI, DT);
1449
2.72k
1450
2.72k
    switch (ICond->getPredicate()) {
1451
2.72k
    case ICmpInst::ICMP_ULT:
1452
30
      ConsequenceCondSet =
1453
30
          buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand,
1454
30
                                     RightOperand, InvalidDomainMap, true);
1455
30
      break;
1456
2.72k
    case ICmpInst::ICMP_ULE:
1457
3
      ConsequenceCondSet =
1458
3
          buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand,
1459
3
                                     RightOperand, InvalidDomainMap, false);
1460
3
      break;
1461
2.72k
    case ICmpInst::ICMP_UGT:
1462
5
      ConsequenceCondSet =
1463
5
          buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand,
1464
5
                                     LeftOperand, InvalidDomainMap, true);
1465
5
      break;
1466
2.72k
    case ICmpInst::ICMP_UGE:
1467
5
      ConsequenceCondSet =
1468
5
          buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand,
1469
5
                                     LeftOperand, InvalidDomainMap, false);
1470
5
      break;
1471
2.72k
    default:
1472
2.68k
      LHS = getPwAff(S, BB, InvalidDomainMap, LeftOperand, NonNeg);
1473
2.68k
      RHS = getPwAff(S, BB, InvalidDomainMap, RightOperand, NonNeg);
1474
2.68k
      ConsequenceCondSet = buildConditionSet(ICond->getPredicate(),
1475
2.68k
                                             isl::manage(LHS), isl::manage(RHS))
1476
2.68k
                               .release();
1477
2.68k
      break;
1478
2.95k
    }
1479
2.95k
  }
1480
2.95k
1481
2.95k
  // If no terminator was given we are only looking for parameter constraints
1482
2.95k
  // under which @p Condition is true/false.
1483
2.95k
  if (!TI)
1484
25
    ConsequenceCondSet = isl_set_params(ConsequenceCondSet);
1485
2.95k
  assert(ConsequenceCondSet);
1486
2.95k
  ConsequenceCondSet = isl_set_coalesce(
1487
2.95k
      isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain)));
1488
2.95k
1489
2.95k
  isl_set *AlternativeCondSet = nullptr;
1490
2.95k
  bool TooComplex =
1491
2.95k
      isl_set_n_basic_set(ConsequenceCondSet) >= MaxDisjunctsInDomain;
1492
2.95k
1493
2.95k
  if (!TooComplex) {
1494
2.95k
    AlternativeCondSet = isl_set_subtract(isl_set_copy(Domain),
1495
2.95k
                                          isl_set_copy(ConsequenceCondSet));
1496
2.95k
    TooComplex =
1497
2.95k
        isl_set_n_basic_set(AlternativeCondSet) >= MaxDisjunctsInDomain;
1498
2.95k
  }
1499
2.95k
1500
2.95k
  if (TooComplex) {
1501
5
    S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : 
DebugLoc()0
,
1502
5
                 TI ? TI->getParent() : 
nullptr0
/* BasicBlock */);
1503
5
    isl_set_free(AlternativeCondSet);
1504
5
    isl_set_free(ConsequenceCondSet);
1505
5
    return false;
1506
5
  }
1507
2.94k
1508
2.94k
  ConditionSets.push_back(ConsequenceCondSet);
1509
2.94k
  ConditionSets.push_back(isl_set_coalesce(AlternativeCondSet));
1510
2.94k
1511
2.94k
  return true;
1512
2.94k
}
1513
1514
/// Build the conditions sets for the terminator @p TI in the @p Domain.
1515
///
1516
/// This will fill @p ConditionSets with the conditions under which control
1517
/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
1518
/// have as many elements as @p TI has successors.
1519
bool buildConditionSets(Scop &S, BasicBlock *BB, Instruction *TI, Loop *L,
1520
                        __isl_keep isl_set *Domain,
1521
                        DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1522
6.05k
                        SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1523
6.05k
  if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
1524
17
    return buildConditionSets(S, BB, SI, L, Domain, InvalidDomainMap,
1525
17
                              ConditionSets);
1526
6.03k
1527
6.03k
  assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
1528
6.03k
1529
6.03k
  if (TI->getNumSuccessors() == 1) {
1530
3.15k
    ConditionSets.push_back(isl_set_copy(Domain));
1531
3.15k
    return true;
1532
3.15k
  }
1533
2.88k
1534
2.88k
  Value *Condition = getConditionFromTerminator(TI);
1535
2.88k
  assert(Condition && "No condition for Terminator");
1536
2.88k
1537
2.88k
  return buildConditionSets(S, BB, Condition, TI, L, Domain, InvalidDomainMap,
1538
2.88k
                            ConditionSets);
1539
2.88k
}
1540
1541
ScopStmt::ScopStmt(Scop &parent, Region &R, StringRef Name,
1542
                   Loop *SurroundingLoop,
1543
                   std::vector<Instruction *> EntryBlockInstructions)
1544
    : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), R(&R),
1545
      Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop),
1546
122
      Instructions(EntryBlockInstructions) {}
1547
1548
ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name,
1549
                   Loop *SurroundingLoop,
1550
                   std::vector<Instruction *> Instructions)
1551
    : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(&bb),
1552
      Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop),
1553
9.15k
      Instructions(Instructions) {}
1554
1555
ScopStmt::ScopStmt(Scop &parent, isl::map SourceRel, isl::map TargetRel,
1556
                   isl::set NewDomain)
1557
    : Parent(parent), InvalidDomain(nullptr), Domain(NewDomain),
1558
24
      Build(nullptr) {
1559
24
  BaseName = getIslCompatibleName("CopyStmt_", "",
1560
24
                                  std::to_string(parent.getCopyStmtsNum()));
1561
24
  isl::id Id = isl::id::alloc(getIslCtx(), getBaseName(), this);
1562
24
  Domain = Domain.set_tuple_id(Id);
1563
24
  TargetRel = TargetRel.set_tuple_id(isl::dim::in, Id);
1564
24
  auto *Access =
1565
24
      new MemoryAccess(this, MemoryAccess::AccessType::MUST_WRITE, TargetRel);
1566
24
  parent.addAccessFunction(Access);
1567
24
  addAccess(Access);
1568
24
  SourceRel = SourceRel.set_tuple_id(isl::dim::in, Id);
1569
24
  Access = new MemoryAccess(this, MemoryAccess::AccessType::READ, SourceRel);
1570
24
  parent.addAccessFunction(Access);
1571
24
  addAccess(Access);
1572
24
}
1573
1574
9.26k
ScopStmt::~ScopStmt() = default;
1575
1576
850
std::string ScopStmt::getDomainStr() const { return Domain.to_str(); }
1577
1578
850
std::string ScopStmt::getScheduleStr() const {
1579
850
  auto *S = getSchedule().release();
1580
850
  if (!S)
1581
0
    return {};
1582
850
  auto Str = stringFromIslObj(S);
1583
850
  isl_map_free(S);
1584
850
  return Str;
1585
850
}
1586
1587
9.12k
void ScopStmt::setInvalidDomain(isl::set ID) { InvalidDomain = ID; }
1588
1589
46.2k
BasicBlock *ScopStmt::getEntryBlock() const {
1590
46.2k
  if (isBlockStmt())
1591
44.0k
    return getBasicBlock();
1592
2.20k
  return getRegion()->getEntry();
1593
2.20k
}
1594
1595
5.29k
unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); }
1596
1597
8.59k
const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
1598
1599
729
Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
1600
729
  return NestLoops[Dimension];
1601
729
}
1602
1603
84
isl::ctx ScopStmt::getIslCtx() const { return Parent.getIslCtx(); }
1604
1605
67.6k
isl::set ScopStmt::getDomain() const { return Domain; }
1606
1607
5.49k
isl::space ScopStmt::getDomainSpace() const { return Domain.get_space(); }
1608
1609
81
isl::id ScopStmt::getDomainId() const { return Domain.get_tuple_id(); }
1610
1611
94
void ScopStmt::printInstructions(raw_ostream &OS) const {
1612
94
  OS << "Instructions {\n";
1613
94
1614
94
  for (Instruction *Inst : Instructions)
1615
177
    OS.indent(16) << *Inst << "\n";
1616
94
1617
94
  OS.indent(12) << "}\n";
1618
94
}
1619
1620
850
void ScopStmt::print(raw_ostream &OS, bool PrintInstructions) const {
1621
850
  OS << "\t" << getBaseName() << "\n";
1622
850
  OS.indent(12) << "Domain :=\n";
1623
850
1624
850
  if (Domain) {
1625
850
    OS.indent(16) << getDomainStr() << ";\n";
1626
850
  } else
1627
0
    OS.indent(16) << "n/a\n";
1628
850
1629
850
  OS.indent(12) << "Schedule :=\n";
1630
850
1631
850
  if (Domain) {
1632
850
    OS.indent(16) << getScheduleStr() << ";\n";
1633
850
  } else
1634
0
    OS.indent(16) << "n/a\n";
1635
850
1636
850
  for (MemoryAccess *Access : MemAccs)
1637
1.73k
    Access->print(OS);
1638
850
1639
850
  if (PrintInstructions)
1640
32
    printInstructions(OS.indent(12));
1641
850
}
1642
1643
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1644
LLVM_DUMP_METHOD void ScopStmt::dump() const { print(dbgs(), true); }
1645
#endif
1646
1647
527
void ScopStmt::removeAccessData(MemoryAccess *MA) {
1648
527
  if (MA->isRead() && 
MA->isOriginalValueKind()474
) {
1649
44
    bool Found = ValueReads.erase(MA->getAccessValue());
1650
44
    (void)Found;
1651
44
    assert(Found && "Expected access data not found");
1652
44
  }
1653
527
  if (MA->isWrite() && 
MA->isOriginalValueKind()53
) {
1654
27
    bool Found = ValueWrites.erase(cast<Instruction>(MA->getAccessValue()));
1655
27
    (void)Found;
1656
27
    assert(Found && "Expected access data not found");
1657
27
  }
1658
527
  if (MA->isWrite() && 
MA->isOriginalAnyPHIKind()53
) {
1659
7
    bool Found = PHIWrites.erase(cast<PHINode>(MA->getAccessInstruction()));
1660
7
    (void)Found;
1661
7
    assert(Found && "Expected access data not found");
1662
7
  }
1663
527
  if (MA->isRead() && 
MA->isOriginalAnyPHIKind()474
) {
1664
14
    bool Found = PHIReads.erase(cast<PHINode>(MA->getAccessInstruction()));
1665
14
    (void)Found;
1666
14
    assert(Found && "Expected access data not found");
1667
14
  }
1668
527
}
1669
1670
362
void ScopStmt::removeMemoryAccess(MemoryAccess *MA) {
1671
362
  // Remove the memory accesses from this statement together with all scalar
1672
362
  // accesses that were caused by it. MemoryKind::Value READs have no access
1673
362
  // instruction, hence would not be removed by this function. However, it is
1674
362
  // only used for invariant LoadInst accesses, its arguments are always affine,
1675
362
  // hence synthesizable, and therefore there are no MemoryKind::Value READ
1676
362
  // accesses to be removed.
1677
3.82k
  auto Predicate = [&](MemoryAccess *Acc) {
1678
3.82k
    return Acc->getAccessInstruction() == MA->getAccessInstruction();
1679
3.82k
  };
1680
1.91k
  for (auto *MA : MemAccs) {
1681
1.91k
    if (Predicate(MA)) {
1682
381
      removeAccessData(MA);
1683
381
      Parent.removeAccessData(MA);
1684
381
    }
1685
1.91k
  }
1686
362
  MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate),
1687
362
                MemAccs.end());
1688
362
  InstructionToAccess.erase(MA->getAccessInstruction());
1689
362
}
1690
1691
276
void ScopStmt::removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting) {
1692
276
  if (AfterHoisting) {
1693
146
    auto MAIt = std::find(MemAccs.begin(), MemAccs.end(), MA);
1694
146
    assert(MAIt != MemAccs.end());
1695
146
    MemAccs.erase(MAIt);
1696
146
1697
146
    removeAccessData(MA);
1698
146
    Parent.removeAccessData(MA);
1699
146
  }
1700
276
1701
276
  auto It = InstructionToAccess.find(MA->getAccessInstruction());
1702
276
  if (It != InstructionToAccess.end()) {
1703
162
    It->second.remove(MA);
1704
162
    if (It->second.empty())
1705
158
      InstructionToAccess.erase(MA->getAccessInstruction());
1706
162
  }
1707
276
}
1708
1709
1
MemoryAccess *ScopStmt::ensureValueRead(Value *V) {
1710
1
  MemoryAccess *Access = lookupInputAccessOf(V);
1711
1
  if (Access)
1712
0
    return Access;
1713
1
1714
1
  ScopArrayInfo *SAI =
1715
1
      Parent.getOrCreateScopArrayInfo(V, V->getType(), {}, MemoryKind::Value);
1716
1
  Access = new MemoryAccess(this, nullptr, MemoryAccess::READ, V, V->getType(),
1717
1
                            true, {}, {}, V, MemoryKind::Value);
1718
1
  Parent.addAccessFunction(Access);
1719
1
  Access->buildAccessRelation(SAI);
1720
1
  addAccess(Access);
1721
1
  Parent.addAccessData(Access);
1722
1
  return Access;
1723
1
}
1724
1725
0
raw_ostream &polly::operator<<(raw_ostream &OS, const ScopStmt &S) {
1726
0
  S.print(OS, PollyPrintInstructions);
1727
0
  return OS;
1728
0
}
1729
1730
//===----------------------------------------------------------------------===//
1731
/// Scop class implement
1732
1733
96
void Scop::setContext(isl::set NewContext) {
1734
96
  Context = NewContext.align_params(Context.get_space());
1735
96
}
1736
1737
namespace {
1738
1739
/// Remap parameter values but keep AddRecs valid wrt. invariant loads.
1740
struct SCEVSensitiveParameterRewriter
1741
    : public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> {
1742
  const ValueToValueMap &VMap;
1743
1744
public:
1745
  SCEVSensitiveParameterRewriter(const ValueToValueMap &VMap,
1746
                                 ScalarEvolution &SE)
1747
11.8k
      : SCEVRewriteVisitor(SE), VMap(VMap) {}
1748
1749
  static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE,
1750
11.8k
                             const ValueToValueMap &VMap) {
1751
11.8k
    SCEVSensitiveParameterRewriter SSPR(VMap, SE);
1752
11.8k
    return SSPR.visit(E);
1753
11.8k
  }
1754
1755
325
  const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {
1756
325
    auto *Start = visit(E->getStart());
1757
325
    auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
1758
325
                                    visit(E->getStepRecurrence(SE)),
1759
325
                                    E->getLoop(), SCEV::FlagAnyWrap);
1760
325
    return SE.getAddExpr(Start, AddRec);
1761
325
  }
1762
1763
6.30k
  const SCEV *visitUnknown(const SCEVUnknown *E) {
1764
6.30k
    if (auto *NewValue = VMap.lookup(E->getValue()))
1765
53
      return SE.getUnknown(NewValue);
1766
6.25k
    return E;
1767
6.25k
  }
1768
};
1769
1770
/// Check whether we should remap a SCEV expression.
1771
struct SCEVFindInsideScop : public SCEVTraversal<SCEVFindInsideScop> {
1772
  const ValueToValueMap &VMap;
1773
  bool FoundInside = false;
1774
  const Scop *S;
1775
1776
public:
1777
  SCEVFindInsideScop(const ValueToValueMap &VMap, ScalarEvolution &SE,
1778
                     const Scop *S)
1779
17.4k
      : SCEVTraversal(*this), VMap(VMap), S(S) {}
1780
1781
  static bool hasVariant(const SCEV *E, ScalarEvolution &SE,
1782
17.4k
                         const ValueToValueMap &VMap, const Scop *S) {
1783
17.4k
    SCEVFindInsideScop SFIS(VMap, SE, S);
1784
17.4k
    SFIS.visitAll(E);
1785
17.4k
    return SFIS.FoundInside;
1786
17.4k
  }
1787
1788
20.9k
  bool follow(const SCEV *E) {
1789
20.9k
    if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) {
1790
4.71k
      FoundInside |= S->getRegion().contains(AddRec->getLoop());
1791
16.2k
    } else if (auto *Unknown = dyn_cast<SCEVUnknown>(E)) {
1792
7.72k
      if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue()))
1793
2.75k
        FoundInside |= S->getRegion().contains(I) && 
!VMap.count(I)1.35k
;
1794
7.72k
    }
1795
20.9k
    return !FoundInside;
1796
20.9k
  }
1797
1798
15.1k
  bool isDone() { return FoundInside; }
1799
};
1800
} // end anonymous namespace
1801
1802
17.4k
const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *E) const {
1803
17.4k
  // Check whether it makes sense to rewrite the SCEV.  (ScalarEvolution
1804
17.4k
  // doesn't like addition between an AddRec and an expression that
1805
17.4k
  // doesn't have a dominance relationship with it.)
1806
17.4k
  if (SCEVFindInsideScop::hasVariant(E, *SE, InvEquivClassVMap, this))
1807
5.66k
    return E;
1808
11.8k
1809
11.8k
  // Rewrite SCEV.
1810
11.8k
  return SCEVSensitiveParameterRewriter::rewrite(E, *SE, InvEquivClassVMap);
1811
11.8k
}
1812
1813
// This table of function names is used to translate parameter names in more
1814
// human-readable names. This makes it easier to interpret Polly analysis
1815
// results.
1816
StringMap<std::string> KnownNames = {
1817
    {"_Z13get_global_idj", "global_id"},
1818
    {"_Z12get_local_idj", "local_id"},
1819
    {"_Z15get_global_sizej", "global_size"},
1820
    {"_Z14get_local_sizej", "local_size"},
1821
    {"_Z12get_work_dimv", "work_dim"},
1822
    {"_Z17get_global_offsetj", "global_offset"},
1823
    {"_Z12get_group_idj", "group_id"},
1824
    {"_Z14get_num_groupsj", "num_groups"},
1825
};
1826
1827
4
static std::string getCallParamName(CallInst *Call) {
1828
4
  std::string Result;
1829
4
  raw_string_ostream OS(Result);
1830
4
  std::string Name = Call->getCalledFunction()->getName();
1831
4
1832
4
  auto Iterator = KnownNames.find(Name);
1833
4
  if (Iterator != KnownNames.end())
1834
3
    Name = "__" + Iterator->getValue();
1835
4
  OS << Name;
1836
4
  for (auto &Operand : Call->arg_operands()) {
1837
3
    ConstantInt *Op = cast<ConstantInt>(&Operand);
1838
3
    OS << "_" << Op->getValue();
1839
3
  }
1840
4
  OS.flush();
1841
4
  return Result;
1842
4
}
1843
1844
1.27k
void Scop::createParameterId(const SCEV *Parameter) {
1845
1.27k
  assert(Parameters.count(Parameter));
1846
1.27k
  assert(!ParameterIds.count(Parameter));
1847
1.27k
1848
1.27k
  std::string ParameterName = "p_" + std::to_string(getNumParams() - 1);
1849
1.27k
1850
1.27k
  if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1851
1.19k
    Value *Val = ValueParameter->getValue();
1852
1.19k
    CallInst *Call = dyn_cast<CallInst>(Val);
1853
1.19k
1854
1.19k
    if (Call && 
isConstCall(Call)7
) {
1855
4
      ParameterName = getCallParamName(Call);
1856
1.19k
    } else if (UseInstructionNames) {
1857
1.19k
      // If this parameter references a specific Value and this value has a name
1858
1.19k
      // we use this name as it is likely to be unique and more useful than just
1859
1.19k
      // a number.
1860
1.19k
      if (Val->hasName())
1861
1.14k
        ParameterName = Val->getName();
1862
50
      else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) {
1863
50
        auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets();
1864
50
        if (LoadOrigin->hasName()) {
1865
43
          ParameterName += "_loaded_from_";
1866
43
          ParameterName +=
1867
43
              LI->getPointerOperand()->stripInBoundsOffsets()->getName();
1868
43
        }
1869
50
      }
1870
1.19k
    }
1871
1.19k
1872
1.19k
    ParameterName = getIslCompatibleName("", ParameterName, "");
1873
1.19k
  }
1874
1.27k
1875
1.27k
  isl::id Id = isl::id::alloc(getIslCtx(), ParameterName,
1876
1.27k
                              const_cast<void *>((const void *)Parameter));
1877
1.27k
  ParameterIds[Parameter] = Id;
1878
1.27k
}
1879
1880
12.6k
void Scop::addParams(const ParameterSetTy &NewParameters) {
1881
12.6k
  for (const SCEV *Parameter : NewParameters) {
1882
3.23k
    // Normalize the SCEV to get the representing element for an invariant load.
1883
3.23k
    Parameter = extractConstantFactor(Parameter, *SE).second;
1884
3.23k
    Parameter = getRepresentingInvariantLoadSCEV(Parameter);
1885
3.23k
1886
3.23k
    if (Parameters.insert(Parameter))
1887
1.27k
      createParameterId(Parameter);
1888
3.23k
  }
1889
12.6k
}
1890
1891
14.2k
isl::id Scop::getIdForParam(const SCEV *Parameter) const {
1892
14.2k
  // Normalize the SCEV to get the representing element for an invariant load.
1893
14.2k
  Parameter = getRepresentingInvariantLoadSCEV(Parameter);
1894
14.2k
  return ParameterIds.lookup(Parameter);
1895
14.2k
}
1896
1897
13
bool Scop::isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const {
1898
13
  return DT.dominates(BB, getEntry());
1899
13
}
1900
1901
void Scop::addUserAssumptions(
1902
    AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI,
1903
1.19k
    DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1904
1.19k
  for (auto &Assumption : AC.assumptions()) {
1905
21
    auto *CI = dyn_cast_or_null<CallInst>(Assumption);
1906
21
    if (!CI || CI->getNumArgOperands() != 1)
1907
0
      continue;
1908
21
1909
21
    bool InScop = contains(CI);
1910
21
    if (!InScop && 
!isDominatedBy(DT, CI->getParent())13
)
1911
0
      continue;
1912
21
1913
21
    auto *L = LI.getLoopFor(CI->getParent());
1914
21
    auto *Val = CI->getArgOperand(0);
1915
21
    ParameterSetTy DetectedParams;
1916
21
    if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) {
1917
0
      ORE.emit(
1918
0
          OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI)
1919
0
          << "Non-affine user assumption ignored.");
1920
0
      continue;
1921
0
    }
1922
21
1923
21
    // Collect all newly introduced parameters.
1924
21
    ParameterSetTy NewParams;
1925
22
    for (auto *Param : DetectedParams) {
1926
22
      Param = extractConstantFactor(Param, *SE).second;
1927
22
      Param = getRepresentingInvariantLoadSCEV(Param);
1928
22
      if (Parameters.count(Param))
1929
18
        continue;
1930
4
      NewParams.insert(Param);
1931
4
    }
1932
21
1933
21
    SmallVector<isl_set *, 2> ConditionSets;
1934
21
    auto *TI = InScop ? 
CI->getParent()->getTerminator()8
:
nullptr13
;
1935
21
    BasicBlock *BB = InScop ? 
CI->getParent()8
:
getRegion().getEntry()13
;
1936
21
    auto *Dom = InScop ? 
DomainMap[BB].copy()8
:
Context.copy()13
;
1937
21
    assert(Dom && "Cannot propagate a nullptr.");
1938
21
    bool Valid = buildConditionSets(*this, BB, Val, TI, L, Dom,
1939
21
                                    InvalidDomainMap, ConditionSets);
1940
21
    isl_set_free(Dom);
1941
21
1942
21
    if (!Valid)
1943
0
      continue;
1944
21
1945
21
    isl_set *AssumptionCtx = nullptr;
1946
21
    if (InScop) {
1947
8
      AssumptionCtx = isl_set_complement(isl_set_params(ConditionSets[1]));
1948
8
      isl_set_free(ConditionSets[0]);
1949
13
    } else {
1950
13
      AssumptionCtx = isl_set_complement(ConditionSets[1]);
1951
13
      AssumptionCtx = isl_set_intersect(AssumptionCtx, ConditionSets[0]);
1952
13
    }
1953
21
1954
21
    // Project out newly introduced parameters as they are not otherwise useful.
1955
21
    if (!NewParams.empty()) {
1956
10
      for (unsigned u = 0; u < isl_set_n_param(AssumptionCtx); 
u++6
) {
1957
6
        auto *Id = isl_set_get_dim_id(AssumptionCtx, isl_dim_param, u);
1958
6
        auto *Param = static_cast<const SCEV *>(isl_id_get_user(Id));
1959
6
        isl_id_free(Id);
1960
6
1961
6
        if (!NewParams.count(Param))
1962
2
          continue;
1963
4
1964
4
        AssumptionCtx =
1965
4
            isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1);
1966
4
      }
1967
4
    }
1968
21
    ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI)
1969
21
             << "Use user assumption: " << stringFromIslObj(AssumptionCtx));
1970
21
    Context = Context.intersect(isl::manage(AssumptionCtx));
1971
21
  }
1972
1.19k
}
1973
1974
1.20k
void Scop::buildContext() {
1975
1.20k
  isl::space Space = isl::space::params_alloc(getIslCtx(), 0);
1976
1.20k
  Context = isl::set::universe(Space);
1977
1.20k
  InvalidContext = isl::set::empty(Space);
1978
1.20k
  AssumedContext = isl::set::universe(Space);
1979
1.20k
}
1980
1981
1.15k
void Scop::addParameterBounds() {
1982
1.15k
  unsigned PDim = 0;
1983
1.21k
  for (auto *Parameter : Parameters) {
1984
1.21k
    ConstantRange SRange = SE->getSignedRange(Parameter);
1985
1.21k
    Context = addRangeBoundsToSet(Context, SRange, PDim++, isl::dim::param);
1986
1.21k
  }
1987
1.15k
}
1988
1989
2.31k
static std::vector<isl::id> getFortranArrayIds(Scop::array_range Arrays) {
1990
2.31k
  std::vector<isl::id> OutermostSizeIds;
1991
4.93k
  for (auto Array : Arrays) {
1992
4.93k
    // To check if an array is a Fortran array, we check if it has a isl_pw_aff
1993
4.93k
    // for its outermost dimension. Fortran arrays will have this since the
1994
4.93k
    // outermost dimension size can be picked up from their runtime description.
1995
4.93k
    // TODO: actually need to check if it has a FAD, but for now this works.
1996
4.93k
    if (Array->getNumberOfDimensions() > 0) {
1997
3.65k
      isl::pw_aff PwAff = Array->getDimensionSizePw(0);
1998
3.65k
      if (!PwAff)
1999
3.64k
        continue;
2000
14
2001
14
      isl::id Id = PwAff.get_dim_id(isl::dim::param, 0);
2002
14
      assert(!Id.is_null() &&
2003
14
             "Invalid Id for PwAff expression in Fortran array");
2004
14
      OutermostSizeIds.push_back(Id);
2005
14
    }
2006
4.93k
  }
2007
2.31k
  return OutermostSizeIds;
2008
2.31k
}
2009
2010
// The FORTRAN array size parameters are known to be non-negative.
2011
static isl::set boundFortranArrayParams(isl::set Context,
2012
1.15k
                                        Scop::array_range Arrays) {
2013
1.15k
  std::vector<isl::id> OutermostSizeIds;
2014
1.15k
  OutermostSizeIds = getFortranArrayIds(Arrays);
2015
1.15k
2016
1.15k
  for (isl::id Id : OutermostSizeIds) {
2017
7
    int dim = Context.find_dim_by_id(isl::dim::param, Id);
2018
7
    Context = Context.lower_bound_si(isl::dim::param, dim, 0);
2019
7
  }
2020
1.15k
2021
1.15k
  return Context;
2022
1.15k
}
2023
2024
1.16k
void Scop::realignParams() {
2025
1.16k
  if (PollyIgnoreParamBounds)
2026
1
    return;
2027
1.15k
2028
1.15k
  // Add all parameters into a common model.
2029
1.15k
  isl::space Space = getFullParamSpace();
2030
1.15k
2031
1.15k
  // Align the parameters of all data structures to the model.
2032
1.15k
  Context = Context.align_params(Space);
2033
1.15k
2034
1.15k
  // Bound the size of the fortran array dimensions.
2035
1.15k
  Context = boundFortranArrayParams(Context, arrays());
2036
1.15k
2037
1.15k
  // As all parameters are known add bounds to them.
2038
1.15k
  addParameterBounds();
2039
1.15k
2040
1.15k
  for (ScopStmt &Stmt : *this)
2041
2.31k
    Stmt.realignParams();
2042
1.15k
  // Simplify the schedule according to the context too.
2043
1.15k
  Schedule = Schedule.gist_domain_params(getContext());
2044
1.15k
}
2045
2046
static isl::set simplifyAssumptionContext(isl::set AssumptionContext,
2047
1.16k
                                          const Scop &S) {
2048
1.16k
  // If we have modeled all blocks in the SCoP that have side effects we can
2049
1.16k
  // simplify the context with the constraints that are needed for anything to
2050
1.16k
  // be executed at all. However, if we have error blocks in the SCoP we already
2051
1.16k
  // assumed some parameter combinations cannot occur and removed them from the
2052
1.16k
  // domains, thus we cannot use the remaining domain to simplify the
2053
1.16k
  // assumptions.
2054
1.16k
  if (!S.hasErrorBlock()) {
2055
1.13k
    auto DomainParameters = S.getDomains().params();
2056
1.13k
    AssumptionContext = AssumptionContext.gist_params(DomainParameters);
2057
1.13k
  }
2058
1.16k
2059
1.16k
  AssumptionContext = AssumptionContext.gist_params(S.getContext());
2060
1.16k
  return AssumptionContext;
2061
1.16k
}
2062
2063
1.16k
void Scop::simplifyContexts() {
2064
1.16k
  // The parameter constraints of the iteration domains give us a set of
2065
1.16k
  // constraints that need to hold for all cases where at least a single
2066
1.16k
  // statement iteration is executed in the whole scop. We now simplify the
2067
1.16k
  // assumed context under the assumption that such constraints hold and at
2068
1.16k
  // least a single statement iteration is executed. For cases where no
2069
1.16k
  // statement instances are executed, the assumptions we have taken about
2070
1.16k
  // the executed code do not matter and can be changed.
2071
1.16k
  //
2072
1.16k
  // WARNING: This only holds if the assumptions we have taken do not reduce
2073
1.16k
  //          the set of statement instances that are executed. Otherwise we
2074
1.16k
  //          may run into a case where the iteration domains suggest that
2075
1.16k
  //          for a certain set of parameter constraints no code is executed,
2076
1.16k
  //          but in the original program some computation would have been
2077
1.16k
  //          performed. In such a case, modifying the run-time conditions and
2078
1.16k
  //          possibly influencing the run-time check may cause certain scops
2079
1.16k
  //          to not be executed.
2080
1.16k
  //
2081
1.16k
  // Example:
2082
1.16k
  //
2083
1.16k
  //   When delinearizing the following code:
2084
1.16k
  //
2085
1.16k
  //     for (long i = 0; i < 100; i++)
2086
1.16k
  //       for (long j = 0; j < m; j++)
2087
1.16k
  //         A[i+p][j] = 1.0;
2088
1.16k
  //
2089
1.16k
  //   we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
2090
1.16k
  //   otherwise we would access out of bound data. Now, knowing that code is
2091
1.16k
  //   only executed for the case m >= 0, it is sufficient to assume p >= 0.
2092
1.16k
  AssumedContext = simplifyAssumptionContext(AssumedContext, *this);
2093
1.16k
  InvalidContext = InvalidContext.align_params(getParamSpace());
2094
1.16k
}
2095
2096
/// Helper to treat non-affine regions and basic blocks the same.
2097
///
2098
///{
2099
2100
/// Return the block that is the representing block for @p RN.
2101
17.0k
static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) {
2102
17.0k
  return RN->isSubRegion() ? 
RN->getNodeAs<Region>()->getEntry()300
2103
17.0k
                           : 
RN->getNodeAs<BasicBlock>()16.7k
;
2104
17.0k
}
2105
2106
/// Return the @p idx'th block that is executed after @p RN.
2107
static inline BasicBlock *
2108
8.78k
getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx) {
2109
8.78k
  if (RN->isSubRegion()) {
2110
107
    assert(idx == 0);
2111
107
    return RN->getNodeAs<Region>()->getExit();
2112
107
  }
2113
8.67k
  return TI->getSuccessor(idx);
2114
8.67k
}
2115
2116
static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI,
2117
11.3k
                               const DominatorTree &DT) {
2118
11.3k
  if (!RN->isSubRegion())
2119
11.1k
    return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT);
2120
218
  for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
2121
594
    if (isErrorBlock(*BB, R, LI, DT))
2122
15
      return true;
2123
218
  
return false203
;
2124
218
}
2125
2126
///}
2127
2128
2.32k
isl::set Scop::getDomainConditions(const ScopStmt *Stmt) const {
2129
2.32k
  return getDomainConditions(Stmt->getEntryBlock());
2130
2.32k
}
2131
2132
19.5k
isl::set Scop::getDomainConditions(BasicBlock *BB) const {
2133
19.5k
  auto DIt = DomainMap.find(BB);
2134
19.5k
  if (DIt != DomainMap.end())
2135
19.5k
    return DIt->getSecond();
2136
16
2137
16
  auto &RI = *R.getRegionInfo();
2138
16
  auto *BBR = RI.getRegionFor(BB);
2139
32
  while (BBR->getEntry() == BB)
2140
16
    BBR = BBR->getParent();
2141
16
  return getDomainConditions(BBR->getEntry());
2142
16
}
2143
2144
bool Scop::buildDomains(Region *R, DominatorTree &DT, LoopInfo &LI,
2145
1.20k
                        DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2146
1.20k
  bool IsOnlyNonAffineRegion = isNonAffineSubRegion(R);
2147
1.20k
  auto *EntryBB = R->getEntry();
2148
1.20k
  auto *L = IsOnlyNonAffineRegion ? 
nullptr18
:
LI.getLoopFor(EntryBB)1.18k
;
2149
1.20k
  int LD = getRelativeLoopDepth(L);
2150
1.20k
  auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx().get(), 0, LD + 1));
2151
1.20k
2152
2.21k
  while (LD-- >= 0) {
2153
1.01k
    L = L->getParentLoop();
2154
1.01k
  }
2155
1.20k
2156
1.20k
  InvalidDomainMap[EntryBB] = isl::manage(isl_set_empty(isl_set_get_space(S)));
2157
1.20k
  DomainMap[EntryBB] = isl::manage(S);
2158
1.20k
2159
1.20k
  if (IsOnlyNonAffineRegion)
2160
18
    return !containsErrorBlock(R->getNode(), *R, LI, DT);
2161
1.18k
2162
1.18k
  if (!buildDomainsWithBranchConstraints(R, DT, LI, InvalidDomainMap))
2163
5
    return false;
2164
1.18k
2165
1.18k
  if (!propagateDomainConstraints(R, DT, LI, InvalidDomainMap))
2166
0
    return false;
2167
1.18k
2168
1.18k
  // Error blocks and blocks dominated by them have been assumed to never be
2169
1.18k
  // executed. Representing them in the Scop does not add any value. In fact,
2170
1.18k
  // it is likely to cause issues during construction of the ScopStmts. The
2171
1.18k
  // contents of error blocks have not been verified to be expressible and
2172
1.18k
  // will cause problems when building up a ScopStmt for them.
2173
1.18k
  // Furthermore, basic blocks dominated by error blocks may reference
2174
1.18k
  // instructions in the error block which, if the error block is not modeled,
2175
1.18k
  // can themselves not be constructed properly. To this end we will replace
2176
1.18k
  // the domains of error blocks and those only reachable via error blocks
2177
1.18k
  // with an empty set. Additionally, we will record for each block under which
2178
1.18k
  // parameter combination it would be reached via an error block in its
2179
1.18k
  // InvalidDomain. This information is needed during load hoisting.
2180
1.18k
  if (!propagateInvalidStmtDomains(R, DT, LI, InvalidDomainMap))
2181
0
    return false;
2182
1.18k
2183
1.18k
  return true;
2184
1.18k
}
2185
2186
/// Adjust the dimensions of @p Dom that was constructed for @p OldL
2187
///        to be compatible to domains constructed for loop @p NewL.
2188
///
2189
/// This function assumes @p NewL and @p OldL are equal or there is a CFG
2190
/// edge from @p OldL to @p NewL.
2191
static isl::set adjustDomainDimensions(Scop &S, isl::set Dom, Loop *OldL,
2192
9.86k
                                       Loop *NewL) {
2193
9.86k
  // If the loops are the same there is nothing to do.
2194
9.86k
  if (NewL == OldL)
2195
6.58k
    return Dom;
2196
3.28k
2197
3.28k
  int OldDepth = S.getRelativeLoopDepth(OldL);
2198
3.28k
  int NewDepth = S.getRelativeLoopDepth(NewL);
2199
3.28k
  // If both loops are non-affine loops there is nothing to do.
2200
3.28k
  if (OldDepth == -1 && 
NewDepth == -1479
)
2201
0
    return Dom;
2202
3.28k
2203
3.28k
  // Distinguish three cases:
2204
3.28k
  //   1) The depth is the same but the loops are not.
2205
3.28k
  //      => One loop was left one was entered.
2206
3.28k
  //   2) The depth increased from OldL to NewL.
2207
3.28k
  //      => One loop was entered, none was left.
2208
3.28k
  //   3) The depth decreased from OldL to NewL.
2209
3.28k
  //      => Loops were left were difference of the depths defines how many.
2210
3.28k
  if (OldDepth == NewDepth) {
2211
12
    assert(OldL->getParentLoop() == NewL->getParentLoop());
2212
12
    Dom = Dom.project_out(isl::dim::set, NewDepth, 1);
2213
12
    Dom = Dom.add_dims(isl::dim::set, 1);
2214
3.26k
  } else if (OldDepth < NewDepth) {
2215
1.42k
    assert(OldDepth + 1 == NewDepth);
2216
1.42k
    auto &R = S.getRegion();
2217
1.42k
    (void)R;
2218
1.42k
    assert(NewL->getParentLoop() == OldL ||
2219
1.42k
           ((!OldL || !R.contains(OldL)) && R.contains(NewL)));
2220
1.42k
    Dom = Dom.add_dims(isl::dim::set, 1);
2221
1.84k
  } else {
2222
1.84k
    assert(OldDepth > NewDepth);
2223
1.84k
    int Diff = OldDepth - NewDepth;
2224
1.84k
    int NumDim = Dom.n_dim();
2225
1.84k
    assert(NumDim >= Diff);
2226
1.84k
    Dom = Dom.project_out(isl::dim::set, NumDim - Diff, Diff);
2227
1.84k
  }
2228
3.28k
2229
3.28k
  return Dom;
2230
3.28k
}
2231
2232
bool Scop::propagateInvalidStmtDomains(
2233
    Region *R, DominatorTree &DT, LoopInfo &LI,
2234
2.44k
    DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2235
2.44k
  ReversePostOrderTraversal<Region *> RTraversal(R);
2236
6.93k
  for (auto *RN : RTraversal) {
2237
6.93k
2238
6.93k
    // Recurse for affine subregions but go on for basic blocks and non-affine
2239
6.93k
    // subregions.
2240
6.93k
    if (RN->isSubRegion()) {
2241
1.36k
      Region *SubRegion = RN->getNodeAs<Region>();
2242
1.36k
      if (!isNonAffineSubRegion(SubRegion)) {
2243
1.26k
        propagateInvalidStmtDomains(SubRegion, DT, LI, InvalidDomainMap);
2244
1.26k
        continue;
2245
1.26k
      }
2246
5.66k
    }
2247
5.66k
2248
5.66k
    bool ContainsErrorBlock = containsErrorBlock(RN, getRegion(), LI, DT);
2249
5.66k
    BasicBlock *BB = getRegionNodeBasicBlock(RN);
2250
5.66k
    isl::set &Domain = DomainMap[BB];
2251
5.66k
    assert(Domain && "Cannot propagate a nullptr");
2252
5.66k
2253
5.66k
    isl::set InvalidDomain = InvalidDomainMap[BB];
2254
5.66k
2255
5.66k
    bool IsInvalidBlock = ContainsErrorBlock || 
Domain.is_subset(InvalidDomain)5.63k
;
2256
5.66k
2257
5.66k
    if (!IsInvalidBlock) {
2258
5.50k
      InvalidDomain = InvalidDomain.intersect(Domain);
2259
5.50k
    } else {
2260
159
      InvalidDomain = Domain;
2261
159
      isl::set DomPar = Domain.params();
2262
159
      recordAssumption(ERRORBLOCK, DomPar, BB->getTerminator()->getDebugLoc(),
2263
159
                       AS_RESTRICTION);
2264
159
      Domain = isl::set::empty(Domain.get_space());
2265
159
    }
2266
5.66k
2267
5.66k
    if (InvalidDomain.is_empty()) {
2268
4.80k
      InvalidDomainMap[BB] = InvalidDomain;
2269
4.80k
      continue;
2270
4.80k
    }
2271
861
2272
861
    auto *BBLoop = getRegionNodeLoop(RN, LI);
2273
861
    auto *TI = BB->getTerminator();
2274
861
    unsigned NumSuccs = RN->isSubRegion() ? 
17
:
TI->getNumSuccessors()854
;
2275
2.08k
    for (unsigned u = 0; u < NumSuccs; 
u++1.22k
) {
2276
1.22k
      auto *SuccBB = getRegionNodeSuccessor(RN, TI, u);
2277
1.22k
2278
1.22k
      // Skip successors outside the SCoP.
2279
1.22k
      if (!contains(SuccBB))
2280
207
        continue;
2281
1.01k
2282
1.01k
      // Skip backedges.
2283
1.01k
      if (DT.dominates(SuccBB, BB))
2284
273
        continue;
2285
741
2286
741
      Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops());
2287
741
2288
741
      auto AdjustedInvalidDomain =
2289
741
          adjustDomainDimensions(*this, InvalidDomain, BBLoop, SuccBBLoop);
2290
741
2291
741
      isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB];
2292
741
      SuccInvalidDomain = SuccInvalidDomain.unite(AdjustedInvalidDomain);
2293
741
      SuccInvalidDomain = SuccInvalidDomain.coalesce();
2294
741
      unsigned NumConjucts = SuccInvalidDomain.n_basic_set();
2295
741
2296
741
      InvalidDomainMap[SuccBB] = SuccInvalidDomain;
2297
741
2298
741
      // Check if the maximal number of domain disjunctions was reached.
2299
741
      // In case this happens we will bail.
2300
741
      if (NumConjucts < MaxDisjunctsInDomain)
2301
741
        continue;
2302
0
2303
0
      InvalidDomainMap.erase(BB);
2304
0
      invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent());
2305
0
      return false;
2306
0
    }
2307
861
2308
861
    InvalidDomainMap[BB] = InvalidDomain;
2309
861
  }
2310
2.44k
2311
2.44k
  return true;
2312
2.44k
}
2313
2314
void Scop::propagateDomainConstraintsToRegionExit(
2315
    BasicBlock *BB, Loop *BBLoop,
2316
    SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, LoopInfo &LI,
2317
5.70k
    DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2318
5.70k
  // Check if the block @p BB is the entry of a region. If so we propagate it's
2319
5.70k
  // domain to the exit block of the region. Otherwise we are done.
2320
5.70k
  auto *RI = R.getRegionInfo();
2321
5.70k
  auto *BBReg = RI ? RI->getRegionFor(BB) : 
nullptr0
;
2322
5.70k
  auto *ExitBB = BBReg ? BBReg->getExit() : 
nullptr0
;
2323
5.70k
  if (!BBReg || BBReg->getEntry() != BB || 
!contains(ExitBB)2.15k
)
2324
4.53k
    return;
2325
1.16k
2326
1.16k
  // Do not propagate the domain if there is a loop backedge inside the region
2327
1.16k
  // that would prevent the exit block from being executed.
2328
1.16k
  auto *L = BBLoop;
2329
1.87k
  while (L && 
contains(L)1.30k
) {
2330
1.26k
    SmallVector<BasicBlock *, 4> LatchBBs;
2331
1.26k
    BBLoop->getLoopLatches(LatchBBs);
2332
1.26k
    for (auto *LatchBB : LatchBBs)
2333
1.26k
      if (BB != LatchBB && 
BBReg->contains(LatchBB)832
)
2334
555
        return;
2335
1.26k
    L = L->getParentLoop();
2336
713
  }
2337
1.16k
2338
1.16k
  isl::set Domain = DomainMap[BB];
2339
609
  assert(Domain && "Cannot propagate a nullptr");
2340
609
2341
609
  Loop *ExitBBLoop = getFirstNonBoxedLoopFor(ExitBB, LI, getBoxedLoops());
2342
609
2343
609
  // Since the dimensions of @p BB and @p ExitBB might be different we have to
2344
609
  // adjust the domain before we can propagate it.
2345
609
  isl::set AdjustedDomain =
2346
609
      adjustDomainDimensions(*this, Domain, BBLoop, ExitBBLoop);
2347
609
  isl::set &ExitDomain = DomainMap[ExitBB];
2348
609
2349
609
  // If the exit domain is not yet created we set it otherwise we "add" the
2350
609
  // current domain.
2351
609
  ExitDomain = ExitDomain ? 
AdjustedDomain.unite(ExitDomain)30
:
AdjustedDomain579
;
2352
609
2353
609
  // Initialize the invalid domain.
2354
609
  InvalidDomainMap[ExitBB] = ExitDomain.empty(ExitDomain.get_space());
2355
609
2356
609
  FinishedExitBlocks.insert(ExitBB);
2357
609
}
2358
2359
bool Scop::buildDomainsWithBranchConstraints(
2360
    Region *R, DominatorTree &DT, LoopInfo &LI,
2361
2.46k
    DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2362
2.46k
  // To create the domain for each block in R we iterate over all blocks and
2363
2.46k
  // subregions in R and propagate the conditions under which the current region
2364
2.46k
  // element is executed. To this end we iterate in reverse post order over R as
2365
2.46k
  // it ensures that we first visit all predecessors of a region node (either a
2366
2.46k
  // basic block or a subregion) before we visit the region node itself.
2367
2.46k
  // Initially, only the domain for the SCoP region entry block is set and from
2368
2.46k
  // there we propagate the current domain to all successors, however we add the
2369
2.46k
  // condition that the successor is actually executed next.
2370
2.46k
  // As we are only interested in non-loop carried constraints here we can
2371
2.46k
  // simply skip loop back edges.
2372
2.46k
2373
2.46k
  SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks;
2374
2.46k
  ReversePostOrderTraversal<Region *> RTraversal(R);
2375
6.97k
  for (auto *RN : RTraversal) {
2376
6.97k
    // Recurse for affine subregions but go on for basic blocks and non-affine
2377
6.97k
    // subregions.
2378
6.97k
    if (RN->isSubRegion()) {
2379
1.37k
      Region *SubRegion = RN->getNodeAs<Region>();
2380
1.37k
      if (!isNonAffineSubRegion(SubRegion)) {
2381
1.27k
        if (!buildDomainsWithBranchConstraints(SubRegion, DT, LI,
2382
1.27k
                                               InvalidDomainMap))
2383
5
          return false;
2384
1.27k
        continue;
2385
1.27k
      }
2386
1.37k
    }
2387
5.70k
2388
5.70k
    if (containsErrorBlock(RN, getRegion(), LI, DT))
2389
37
      HasErrorBlock = true;
2390
5.70k
2391
5.70k
    BasicBlock *BB = getRegionNodeBasicBlock(RN);
2392
5.70k
    Instruction *TI = BB->getTerminator();
2393
5.70k
2394
5.70k
    if (isa<UnreachableInst>(TI))
2395
0
      continue;
2396
5.70k
2397
5.70k
    isl::set Domain = DomainMap.lookup(BB);
2398
5.70k
    if (!Domain)
2399
0
      continue;
2400
5.70k
    MaxLoopDepth = std::max(MaxLoopDepth, isl_set_n_dim(Domain.get()));
2401
5.70k
2402
5.70k
    auto *BBLoop = getRegionNodeLoop(RN, LI);
2403
5.70k
    // Propagate the domain from BB directly to blocks that have a superset
2404
5.70k
    // domain, at the moment only region exit nodes of regions that start in BB.
2405
5.70k
    propagateDomainConstraintsToRegionExit(BB, BBLoop, FinishedExitBlocks, LI,
2406
5.70k
                                           InvalidDomainMap);
2407
5.70k
2408
5.70k
    // If all successors of BB have been set a domain through the propagation
2409
5.70k
    // above we do not need to build condition sets but can just skip this
2410
5.70k
    // block. However, it is important to note that this is a local property
2411
5.70k
    // with regards to the region @p R. To this end FinishedExitBlocks is a
2412
5.70k
    // local variable.
2413
5.87k
    auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) {
2414
5.87k
      return FinishedExitBlocks.count(SuccBB);
2415
5.87k
    };
2416
5.70k
    if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit))
2417
306
      continue;
2418
5.39k
2419
5.39k
    // Build the condition sets for the successor nodes of the current region
2420
5.39k
    // node. If it is a non-affine subregion we will always execute the single
2421
5.39k
    // exit node, hence the single entry node domain is the condition set. For
2422
5.39k
    // basic blocks we use the helper function buildConditionSets.
2423
5.39k
    SmallVector<isl_set *, 8> ConditionSets;
2424
5.39k
    if (RN->isSubRegion())
2425
100
      ConditionSets.push_back(Domain.copy());
2426
5.29k
    else if (!buildConditionSets(*this, BB, TI, BBLoop, Domain.get(),
2427
5.29k
                                 InvalidDomainMap, ConditionSets))
2428
5
      return false;
2429
5.38k
2430
5.38k
    // Now iterate over the successors and set their initial domain based on
2431
5.38k
    // their condition set. We skip back edges here and have to be careful when
2432
5.38k
    // we leave a loop not to keep constraints over a dimension that doesn't
2433
5.38k
    // exist anymore.
2434
5.38k
    assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
2435
12.9k
    for (unsigned u = 0, e = ConditionSets.size(); u < e; 
u++7.56k
) {
2436
7.56k
      isl::set CondSet = isl::manage(ConditionSets[u]);
2437
7.56k
      BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
2438
7.56k
2439
7.56k
      // Skip blocks outside the region.
2440
7.56k
      if (!contains(SuccBB))
2441
1.35k
        continue;
2442
6.20k
2443
6.20k
      // If we propagate the domain of some block to "SuccBB" we do not have to
2444
6.20k
      // adjust the domain.
2445
6.20k
      if (FinishedExitBlocks.count(SuccBB))
2446
539
        continue;
2447
5.67k
2448
5.67k
      // Skip back edges.
2449
5.67k
      if (DT.dominates(SuccBB, BB))
2450
1.70k
        continue;
2451
3.96k
2452
3.96k
      Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops());
2453
3.96k
2454
3.96k
      CondSet = adjustDomainDimensions(*this, CondSet, BBLoop, SuccBBLoop);
2455
3.96k
2456
3.96k
      // Set the domain for the successor or merge it with an existing domain in
2457
3.96k
      // case there are multiple paths (without loop back edges) to the
2458
3.96k
      // successor block.
2459
3.96k
      isl::set &SuccDomain = DomainMap[SuccBB];
2460
3.96k
2461
3.96k
      if (SuccDomain) {
2462
27
        SuccDomain = SuccDomain.unite(CondSet).coalesce();
2463
3.94k
      } else {
2464
3.94k
        // Initialize the invalid domain.
2465
3.94k
        InvalidDomainMap[SuccBB] = CondSet.empty(CondSet.get_space());
2466
3.94k
        SuccDomain = CondSet;
2467
3.94k
      }
2468
3.96k
2469
3.96k
      SuccDomain = SuccDomain.detect_equalities();
2470
3.96k
2471
3.96k
      // Check if the maximal number of domain disjunctions was reached.
2472
3.96k
      // In case this happens we will clean up and bail.
2473
3.96k
      if (SuccDomain.n_basic_set() < MaxDisjunctsInDomain)
2474
3.96k
        continue;
2475
0
2476
0
      invalidate(COMPLEXITY, DebugLoc());
2477
0
      while (++u < ConditionSets.size())
2478
0
        isl_set_free(ConditionSets[u]);
2479
0
      return false;
2480
0
    }
2481
5.38k
  }
2482
2.46k
2483
2.46k
  
return true2.45k
;
2484
2.46k
}
2485
2486
isl::set Scop::getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain,
2487
                                               DominatorTree &DT,
2488
5.66k
                                               LoopInfo &LI) {
2489
5.66k
  // If @p BB is the ScopEntry we are done
2490
5.66k
  if (R.getEntry() == BB)
2491
1.18k
    return isl::set::universe(Domain.get_space());
2492
4.48k
2493
4.48k
  // The region info of this function.
2494
4.48k
  auto &RI = *R.getRegionInfo();
2495
4.48k
2496
4.48k
  Loop *BBLoop = getFirstNonBoxedLoopFor(BB, LI, getBoxedLoops());
2497
4.48k
2498
4.48k
  // A domain to collect all predecessor domains, thus all conditions under
2499
4.48k
  // which the block is executed. To this end we start with the empty domain.
2500
4.48k
  isl::set PredDom = isl::set::empty(Domain.get_space());
2501
4.48k
2502
4.48k
  // Set of regions of which the entry block domain has been propagated to BB.
2503
4.48k
  // all predecessors inside any of the regions can be skipped.
2504
4.48k
  SmallSet<Region *, 8> PropagatedRegions;
2505
4.48k
2506
5.56k
  for (auto *PredBB : predecessors(BB)) {
2507
5.56k
    // Skip backedges.
2508
5.56k
    if (DT.dominates(BB, PredBB))
2509
698
      continue;
2510
4.86k
2511
4.86k
    // If the predecessor is in a region we used for propagation we can skip it.
2512
4.86k
    auto PredBBInRegion = [PredBB](Region *PR) 
{ return PR->contains(PredBB); }371
;
2513
4.86k
    if (std::any_of(PropagatedRegions.begin(), PropagatedRegions.end(),
2514
4.86k
                    PredBBInRegion)) {
2515
320
      continue;
2516
320
    }
2517
4.54k
2518
4.54k
    // Check if there is a valid region we can use for propagation, thus look
2519
4.54k
    // for a region that contains the predecessor and has @p BB as exit block.
2520
4.54k
    auto *PredR = RI.getRegionFor(PredBB);
2521
4.54k
    while (PredR->getExit() != BB && 
!PredR->contains(BB)3.34k
)
2522
0
      PredR->getParent();
2523
4.54k
2524
4.54k
    // If a valid region for propagation was found use the entry of that region
2525
4.54k
    // for propagation, otherwise the PredBB directly.
2526
4.54k
    if (PredR->getExit() == BB) {
2527
1.19k
      PredBB = PredR->getEntry();
2528
1.19k
      PropagatedRegions.insert(PredR);
2529
1.19k
    }
2530
4.54k
2531
4.54k
    isl::set PredBBDom = getDomainConditions(PredBB);
2532
4.54k
    Loop *PredBBLoop = getFirstNonBoxedLoopFor(PredBB, LI, getBoxedLoops());
2533
4.54k
    PredBBDom = adjustDomainDimensions(*this, PredBBDom, PredBBLoop, BBLoop);
2534
4.54k
    PredDom = PredDom.unite(PredBBDom);
2535
4.54k
  }
2536
4.48k
2537
4.48k
  return PredDom;
2538
4.48k
}
2539
2540
bool Scop::propagateDomainConstraints(
2541
    Region *R, DominatorTree &DT, LoopInfo &LI,
2542
2.44k
    DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2543
2.44k
  // Iterate over the region R and propagate the domain constrains from the
2544
2.44k
  // predecessors to the current node. In contrast to the
2545
2.44k
  // buildDomainsWithBranchConstraints function, this one will pull the domain
2546
2.44k
  // information from the predecessors instead of pushing it to the successors.
2547
2.44k
  // Additionally, we assume the domains to be already present in the domain
2548
2.44k
  // map here. However, we iterate again in reverse post order so we know all
2549
2.44k
  // predecessors have been visited before a block or non-affine subregion is
2550
2.44k
  // visited.
2551
2.44k
2552
2.44k
  ReversePostOrderTraversal<Region *> RTraversal(R);
2553
6.93k
  for (auto *RN : RTraversal) {
2554
6.93k
    // Recurse for affine subregions but go on for basic blocks and non-affine
2555
6.93k
    // subregions.
2556
6.93k
    if (RN->isSubRegion()) {
2557
1.36k
      Region *SubRegion = RN->getNodeAs<Region>();
2558
1.36k
      if (!isNonAffineSubRegion(SubRegion)) {
2559
1.26k
        if (!propagateDomainConstraints(SubRegion, DT, LI, InvalidDomainMap))
2560
0
          return false;
2561
1.26k
        continue;
2562
1.26k
      }
2563
1.36k
    }
2564
5.66k
2565
5.66k
    BasicBlock *BB = getRegionNodeBasicBlock(RN);
2566
5.66k
    isl::set &Domain = DomainMap[BB];
2567
5.66k
    assert(Domain);
2568
5.66k
2569
5.66k
    // Under the union of all predecessor conditions we can reach this block.
2570
5.66k
    isl::set PredDom = getPredecessorDomainConstraints(BB, Domain, DT, LI);
2571
5.66k
    Domain = Domain.intersect(PredDom).coalesce();
2572
5.66k
    Domain = Domain.align_params(getParamSpace());
2573
5.66k
2574
5.66k
    Loop *BBLoop = getRegionNodeLoop(RN, LI);
2575
5.66k
    if (BBLoop && 
BBLoop->getHeader() == BB4.90k
&&
contains(BBLoop)1.70k
)
2576
1.69k
      if (!addLoopBoundsToHeaderDomain(BBLoop, LI, InvalidDomainMap))
2577
0
        return false;
2578
5.66k
  }
2579
2.44k
2580
2.44k
  return true;
2581
2.44k
}
2582
2583
/// Create a map to map from a given iteration to a subsequent iteration.
2584
///
2585
/// This map maps from SetSpace -> SetSpace where the dimensions @p Dim
2586
/// is incremented by one and all other dimensions are equal, e.g.,
2587
///             [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3]
2588
///
2589
/// if @p Dim is 2 and @p SetSpace has 4 dimensions.
2590
1.69k
static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim) {
2591
1.69k
  isl::space MapSpace = SetSpace.map_from_set();
2592
1.69k
  isl::map NextIterationMap = isl::map::universe(MapSpace);
2593
3.97k
  for (unsigned u = 0; u < NextIterationMap.dim(isl::dim::in); 
u++2.27k
)
2594
2.27k
    if (u != Dim)
2595
572
      NextIterationMap =
2596
572
          NextIterationMap.equate(isl::dim::in, u, isl::dim::out, u);
2597
1.69k
  isl::constraint C =
2598
1.69k
      isl::constraint::alloc_equality(isl::local_space(MapSpace));
2599
1.69k
  C = C.set_constant_si(1);
2600
1.69k
  C = C.set_coefficient_si(isl::dim::in, Dim, 1);
2601
1.69k
  C = C.set_coefficient_si(isl::dim::out, Dim, -1);
2602
1.69k
  NextIterationMap = NextIterationMap.add_constraint(C);
2603
1.69k
  return NextIterationMap;
2604
1.69k
}
2605
2606
bool Scop::addLoopBoundsToHeaderDomain(
2607
1.69k
    Loop *L, LoopInfo &LI, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
2608
1.69k
  int LoopDepth = getRelativeLoopDepth(L);
2609
1.69k
  assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
2610
1.69k
2611
1.69k
  BasicBlock *HeaderBB = L->getHeader();
2612
1.69k
  assert(DomainMap.count(HeaderBB));
2613
1.69k
  isl::set &HeaderBBDom = DomainMap[HeaderBB];
2614
1.69k
2615
1.69k
  isl::map NextIterationMap =
2616
1.69k
      createNextIterationMap(HeaderBBDom.get_space(), LoopDepth);
2617
1.69k
2618
1.69k
  isl::set UnionBackedgeCondition = HeaderBBDom.empty(HeaderBBDom.get_space());
2619
1.69k
2620
1.69k
  SmallVector<BasicBlock *, 4> LatchBlocks;
2621
1.69k
  L->getLoopLatches(LatchBlocks);
2622
1.69k
2623
1.70k
  for (BasicBlock *LatchBB : LatchBlocks) {
2624
1.70k
    // If the latch is only reachable via error statements we skip it.
2625
1.70k
    isl::set LatchBBDom = DomainMap.lookup(LatchBB);
2626
1.70k
    if (!LatchBBDom)
2627
0
      continue;
2628
1.70k
2629
1.70k
    isl::set BackedgeCondition = nullptr;
2630
1.70k
2631
1.70k
    Instruction *TI = LatchBB->getTerminator();
2632
1.70k
    BranchInst *BI = dyn_cast<BranchInst>(TI);
2633
1.70k
    assert(BI && "Only branch instructions allowed in loop latches");
2634
1.70k
2635
1.70k
    if (BI->isUnconditional())
2636
938
      BackedgeCondition = LatchBBDom;
2637
762
    else {
2638
762
      SmallVector<isl_set *, 8> ConditionSets;
2639
762
      int idx = BI->getSuccessor(0) != HeaderBB;
2640
762
      if (!buildConditionSets(*this, LatchBB, TI, L, LatchBBDom.get(),
2641
762
                              InvalidDomainMap, ConditionSets))
2642
0
        return false;
2643
762
2644
762
      // Free the non back edge condition set as we do not need it.
2645
762
      isl_set_free(ConditionSets[1 - idx]);
2646
762
2647
762
      BackedgeCondition = isl::manage(ConditionSets[idx]);
2648
762
    }
2649
1.70k
2650
1.70k
    int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
2651
1.70k
    assert(LatchLoopDepth >= LoopDepth);
2652
1.70k
    BackedgeCondition = BackedgeCondition.project_out(
2653
1.70k
        isl::dim::set, LoopDepth + 1, LatchLoopDepth - LoopDepth);
2654
1.70k
    UnionBackedgeCondition = UnionBackedgeCondition.unite(BackedgeCondition);
2655
1.70k
  }
2656
1.69k
2657
1.69k
  isl::map ForwardMap = ForwardMap.lex_le(HeaderBBDom.get_space());
2658
2.27k
  for (int i = 0; i < LoopDepth; 
i++572
)
2659
572
    ForwardMap = ForwardMap.equate(isl::dim::in, i, isl::dim::out, i);
2660
1.69k
2661
1.69k
  isl::set UnionBackedgeConditionComplement =
2662
1.69k
      UnionBackedgeCondition.complement();
2663
1.69k
  UnionBackedgeConditionComplement =
2664
1.69k
      UnionBackedgeConditionComplement.lower_bound_si(isl::dim::set, LoopDepth,
2665
1.69k
                                                      0);
2666
1.69k
  UnionBackedgeConditionComplement =
2667
1.69k
      UnionBackedgeConditionComplement.apply(ForwardMap);
2668
1.69k
  HeaderBBDom = HeaderBBDom.subtract(UnionBackedgeConditionComplement);
2669
1.69k
  HeaderBBDom = HeaderBBDom.apply(NextIterationMap);
2670
1.69k
2671
1.69k
  auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
2672
1.69k
  HeaderBBDom = Parts.second;
2673
1.69k
2674
1.69k
  // Check if there is a <nsw> tagged AddRec for this loop and if so do not add
2675
1.69k
  // the bounded assumptions to the context as they are already implied by the
2676
1.69k
  // <nsw> tag.
2677
1.69k
  if (Affinator.hasNSWAddRecForLoop(L))
2678
1.31k
    return true;
2679
386
2680
386
  isl::set UnboundedCtx = Parts.first.params();
2681
386
  recordAssumption(INFINITELOOP, UnboundedCtx,
2682
386
                   HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
2683
386
  return true;
2684
386
}
2685
2686
int Scop::NextScopID = 0;
2687
2688
std::string Scop::CurrentFunc;
2689
2690
1.20k
int Scop::getNextID(std::string ParentFunc) {
2691
1.20k
  if (ParentFunc != CurrentFunc) {
2692
1.18k
    CurrentFunc = ParentFunc;
2693
1.18k
    NextScopID = 0;
2694
1.18k
  }
2695
1.20k
  return NextScopID++;
2696
1.20k
}
2697
2698
Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
2699
           DominatorTree &DT, ScopDetection::DetectionContext &DC,
2700
           OptimizationRemarkEmitter &ORE)
2701
    : IslCtx(isl_ctx_alloc(), isl_ctx_free), SE(&ScalarEvolution), DT(&DT),
2702
      R(R), name(None), HasSingleExitEdge(R.getExitingBlock()), DC(DC),
2703
      ORE(ORE), Affinator(this, LI),
2704
1.20k
      ID(getNextID((*R.getEntry()->getParent()).getName().str())) {
2705
1.20k
  if (IslOnErrorAbort)
2706
1.20k
    isl_options_set_on_error(getIslCtx().get(), ISL_ON_ERROR_ABORT);
2707
1.20k
  buildContext();
2708
1.20k
}
2709
2710
1.18k
Scop::~Scop() = default;
2711
2712
6.97k
void Scop::removeFromStmtMap(ScopStmt &Stmt) {
2713
6.97k
  for (Instruction *Inst : Stmt.getInstructions())
2714
2.16k
    InstStmtMap.erase(Inst);
2715
6.97k
2716
6.97k
  if (Stmt.isRegionStmt()) {
2717
44
    for (BasicBlock *BB : Stmt.getRegion()->blocks()) {
2718
44
      StmtMap.erase(BB);
2719
44
      // Skip entry basic block, as its instructions are already deleted as
2720
44
      // part of the statement's instruction list.
2721
44
      if (BB == Stmt.getEntryBlock())
2722
17
        continue;
2723
27
      for (Instruction &Inst : *BB)
2724
60
        InstStmtMap.erase(&Inst);
2725
27
    }
2726
6.95k
  } else {
2727
6.95k
    auto StmtMapIt = StmtMap.find(Stmt.getBasicBlock());
2728
6.95k
    if (StmtMapIt != StmtMap.end())
2729
6.95k
      StmtMapIt->second.erase(std::remove(StmtMapIt->second.begin(),
2730
6.95k
                                          StmtMapIt->second.end(), &Stmt),
2731
6.95k
                              StmtMapIt->second.end());
2732
6.95k
    for (Instruction *Inst : Stmt.getInstructions())
2733
2.13k
      InstStmtMap.erase(Inst);
2734
6.95k
  }
2735
6.97k
}
2736
2737
void Scop::removeStmts(std::function<bool(ScopStmt &)> ShouldDelete,
2738
3.59k
                       bool AfterHoisting) {
2739
23.9k
  for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) {
2740
20.4k
    if (!ShouldDelete(*StmtIt)) {
2741
13.4k
      StmtIt++;
2742
13.4k
      continue;
2743
13.4k
    }
2744
6.97k
2745
6.97k
    // Start with removing all of the statement's accesses including erasing it
2746
6.97k
    // from all maps that are pointing to them.
2747
6.97k
    // Make a temporary copy because removing MAs invalidates the iterator.
2748
6.97k
    SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end());
2749
6.97k
    for (MemoryAccess *MA : MAList)
2750
192
      StmtIt->removeSingleMemoryAccess(MA, AfterHoisting);
2751
6.97k
2752
6.97k
    removeFromStmtMap(*StmtIt);
2753
6.97k
    StmtIt = Stmts.erase(StmtIt);
2754
6.97k
  }
2755
3.59k
}
2756
2757
1.19k
void Scop::removeStmtNotInDomainMap() {
2758
9.12k
  auto ShouldDelete = [this](ScopStmt &Stmt) -> bool {
2759
9.12k
    isl::set Domain = DomainMap.lookup(Stmt.getEntryBlock());
2760
9.12k
    if (!Domain)
2761
0
      return true;
2762
9.12k
    return Domain.is_empty();
2763
9.12k
  };
2764
1.19k
  removeStmts(ShouldDelete, false);
2765
1.19k
}
2766
2767
2.39k
void Scop::simplifySCoP(bool AfterHoisting) {
2768
11.2k
  auto ShouldDelete = [AfterHoisting](ScopStmt &Stmt) -> bool {
2769
11.2k
    // Never delete statements that contain calls to debug functions.
2770
11.2k
    if (hasDebugCall(&Stmt))
2771
2
      return false;
2772
11.2k
2773
11.2k
    bool RemoveStmt = Stmt.isEmpty();
2774
11.2k
2775
11.2k
    // Remove read only statements only after invariant load hoisting.
2776
11.2k
    if (!RemoveStmt && 
AfterHoisting4.60k
) {
2777
2.27k
      bool OnlyRead = true;
2778
3.73k
      for (MemoryAccess *MA : Stmt) {
2779
3.73k
        if (MA->isRead())
2780
1.51k
          continue;
2781
2.22k
2782
2.22k
        OnlyRead = false;
2783
2.22k
        break;
2784
2.22k
      }
2785
2.27k
2786
2.27k
      RemoveStmt = OnlyRead;
2787
2.27k
    }
2788
11.2k
    return RemoveStmt;
2789
11.2k
  };
2790
2.39k
2791
2.39k
  removeStmts(ShouldDelete, AfterHoisting);
2792
2.39k
}
2793
2794
5.82k
InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) {
2795
5.82k
  LoadInst *LInst = dyn_cast<LoadInst>(Val);
2796
5.82k
  if (!LInst)
2797
3.51k
    return nullptr;
2798
2.31k
2799
2.31k
  if (Value *Rep = InvEquivClassVMap.lookup(LInst))
2800
2
    LInst = cast<LoadInst>(Rep);
2801
2.31k
2802
2.31k
  Type *Ty = LInst->getType();
2803
2.31k
  const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
2804
2.31k
  for (auto &IAClass : InvariantEquivClasses) {
2805
276
    if (PointerSCEV != IAClass.IdentifyingPointer || 
Ty != IAClass.AccessType87
)
2806
191
      continue;
2807
85
2808
85
    auto &MAs = IAClass.InvariantAccesses;
2809
85
    for (auto *MA : MAs)
2810
91
      if (MA->getAccessInstruction() == Val)
2811
83
        return &IAClass;
2812
85
  }
2813
2.31k
2814
2.31k
  
return nullptr2.22k
;
2815
2.31k
}
2816
2817
ScopArrayInfo *Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
2818
                                              ArrayRef<const SCEV *> Sizes,
2819
                                              MemoryKind Kind,
2820
4.99k
                                              const char *BaseName) {
2821
4.99k
  assert((BasePtr || BaseName) &&
2822
4.99k
         "BasePtr and BaseName can not be nullptr at the same time.");
2823
4.99k
  assert(!(BasePtr && BaseName) && "BaseName is redundant.");
2824
4.99k
  auto &SAI = BasePtr ? 
ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]4.91k
2825
4.99k
                      : 
ScopArrayNameMap[BaseName]85
;
2826
4.99k
  if (!SAI) {
2827
2.57k
    auto &DL = getFunction().getParent()->getDataLayout();
2828
2.57k
    SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind,
2829
2.57k
                                DL, this, BaseName));
2830
2.57k
    ScopArrayInfoSet.insert(SAI.get());
2831
2.57k
  } else {
2832
2.42k
    SAI->updateElementType(ElementType);
2833
2.42k
    // In case of mismatching array sizes, we bail out by setting the run-time
2834
2.42k
    // context to false.
2835
2.42k
    if (!SAI->updateSizes(Sizes))
2836
0
      invalidate(DELINEARIZATION, DebugLoc());
2837
2.42k
  }
2838
4.99k
  return SAI.get();
2839
4.99k
}
2840
2841
ScopArrayInfo *Scop::createScopArrayInfo(Type *ElementType,
2842
                                         const std::string &BaseName,
2843
85
                                         const std::vector<unsigned> &Sizes) {
2844
85
  auto *DimSizeType = Type::getInt64Ty(getSE()->getContext());
2845
85
  std::vector<const SCEV *> SCEVSizes;
2846
85
2847
85
  for (auto size : Sizes)
2848
168
    if (size)
2849
168
      SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));
2850
0
    else
2851
0
      SCEVSizes.push_back(nullptr);
2852
85
2853
85
  auto *SAI = getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes,
2854
85
                                       MemoryKind::Array, BaseName.c_str());
2855
85
  return SAI;
2856
85
}
2857
2858
const ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr,
2859
530
                                                  MemoryKind Kind) {
2860
530
  auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
2861
530
  return SAI;
2862
530
}
2863
2864
93
const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
2865
93
  auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind);
2866
93
  assert(SAI && "No ScopArrayInfo available for this base pointer");
2867
93
  return SAI;
2868
93
}
2869
2870
0
std::string Scop::getContextStr() const { return getContext().to_str(); }
2871
2872
0
std::string Scop::getAssumedContextStr() const {
2873
0
  assert(AssumedContext && "Assumed context not yet built");
2874
0
  return AssumedContext.to_str();
2875
0
}
2876
2877
0
std::string Scop::getInvalidContextStr() const {
2878
0
  return InvalidContext.to_str();
2879
0
}
2880
2881
841
std::string Scop::getNameStr() const {
2882
841
  std::string ExitName, EntryName;
2883
841
  std::tie(EntryName, ExitName) = getEntryExitStr();
2884
841
  return EntryName + "---" + ExitName;
2885
841
}
2886
2887
851
std::pair<std::string, std::string> Scop::getEntryExitStr() const {
2888
851
  std::string ExitName, EntryName;
2889
851
  raw_string_ostream ExitStr(ExitName);
2890
851
  raw_string_ostream EntryStr(EntryName);
2891
851
2892
851
  R.getEntry()->printAsOperand(EntryStr, false);
2893
851
  EntryStr.str();
2894
851
2895
851
  if (R.getExit()) {
2896
847
    R.getExit()->printAsOperand(ExitStr, false);
2897
847
    ExitStr.str();
2898
847
  } else
2899
4
    ExitName = "FunctionExit";
2900
851
2901
851
  return std::make_pair(EntryName, ExitName);
2902
851
}
2903
2904
34.5k
isl::set Scop::getContext() const { return Context; }
2905
10.1k
isl::space Scop::getParamSpace() const { return getContext().get_space(); }
2906
2907
1.15k
isl::space Scop::getFullParamSpace() const {
2908
1.15k
  std::vector<isl::id> FortranIDs;
2909
1.15k
  FortranIDs = getFortranArrayIds(arrays());
2910
1.15k
2911
1.15k
  isl::space Space = isl::space::params_alloc(
2912
1.15k
      getIslCtx(), ParameterIds.size() + FortranIDs.size());
2913
1.15k
2914
1.15k
  unsigned PDim = 0;
2915
1.21k
  for (const SCEV *Parameter : Parameters) {
2916
1.21k
    isl::id Id = getIdForParam(Parameter);
2917
1.21k
    Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
2918
1.21k
  }
2919
1.15k
2920
1.15k
  for (isl::id Id : FortranIDs)
2921
7
    Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
2922
1.15k
2923
1.15k
  return Space;
2924
1.15k
}
2925
2926
5.01k
isl::set Scop::getAssumedContext() const {
2927
5.01k
  assert(AssumedContext && "Assumed context not yet built");
2928
5.01k
  return AssumedContext;
2929
5.01k
}
2930
2931
1.16k
bool Scop::isProfitable(bool ScalarsAreUnprofitable) const {
2932
1.16k
  if (PollyProcessUnprofitable)
2933
1.15k
    return true;
2934
3
2935
3
  if (isEmpty())
2936
0
    return false;
2937
3
2938
3
  unsigned OptimizableStmtsOrLoops = 0;
2939
14
  for (auto &Stmt : *this) {
2940
14
    if (Stmt.getNumIterators() == 0)
2941
0
      continue;
2942
14
2943
14
    bool ContainsArrayAccs = false;
2944
14
    bool ContainsScalarAccs = false;
2945
33
    for (auto *MA : Stmt) {
2946
33
      if (MA->isRead())
2947
15
        continue;
2948
18
      ContainsArrayAccs |= MA->isLatestArrayKind();
2949
18
      ContainsScalarAccs |= MA->isLatestScalarKind();
2950
18
    }
2951
14
2952
14
    if (!ScalarsAreUnprofitable || 
(9
ContainsArrayAccs9
&&
!ContainsScalarAccs4
))
2953
6
      OptimizableStmtsOrLoops += Stmt.getNumIterators();
2954
14
  }
2955
3
2956
3
  return OptimizableStmtsOrLoops > 1;
2957
3
}
2958
2959
3.89k
bool Scop::hasFeasibleRuntimeContext() const {
2960
3.89k
  auto PositiveContext = getAssumedContext();
2961
3.89k
  auto NegativeContext = getInvalidContext();
2962
3.89k
  PositiveContext = addNonEmptyDomainConstraints(PositiveContext);
2963
3.89k
  // addNonEmptyDomainConstraints returns null if ScopStmts have a null domain
2964
3.89k
  if (!PositiveContext)
2965
8
    return false;
2966
3.88k
2967
3.88k
  bool IsFeasible = !(PositiveContext.is_empty() ||
2968
3.88k
                      
PositiveContext.is_subset(NegativeContext)3.82k
);
2969
3.88k
  if (!IsFeasible)
2970
82
    return false;
2971
3.80k
2972
3.80k
  auto DomainContext = getDomains().params();
2973
3.80k
  IsFeasible = !DomainContext.is_subset(NegativeContext);
2974
3.80k
  IsFeasible &= !getContext().is_subset(NegativeContext);
2975
3.80k
2976
3.80k
  return IsFeasible;
2977
3.80k
}
2978
2979
3.89k
isl::set Scop::addNonEmptyDomainConstraints(isl::set C) const {
2980
3.89k
  isl::set DomainContext = getDomains().params();
2981
3.89k
  return C.intersect_params(DomainContext);
2982
3.89k
}
2983
2984
1.33k
MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) {
2985
1.33k
  Value *PointerBase = MA->getOriginalBaseAddr();
2986
1.33k
2987
1.33k
  auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase);
2988
1.33k
  if (!PointerBaseInst)
2989
1.11k
    return nullptr;
2990
221
2991
221
  auto *BasePtrStmt = getStmtFor(PointerBaseInst);
2992
221
  if (!BasePtrStmt)
2993
221
    return nullptr;
2994
0
2995
0
  return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst);
2996
0
}
2997
2998
668
static std::string toString(AssumptionKind Kind) {
2999
668
  switch (Kind) {
3000
668
  case ALIASING:
3001
5
    return "No-aliasing";
3002
668
  case INBOUNDS:
3003
114
    return "Inbounds";
3004
668
  case WRAPPING:
3005
345
    return "No-overflows";
3006
668
  case UNSIGNED:
3007
87
    return "Signed-unsigned";
3008
668
  case COMPLEXITY:
3009
8
    return "Low complexity";
3010
668
  case PROFITABLE:
3011
2
    return "Profitable";
3012
668
  case ERRORBLOCK:
3013
22
    return "No-error";
3014
668
  case INFINITELOOP:
3015
73
    return "Finite loop";
3016
668
  case INVARIANTLOAD:
3017
10
    return "Invariant load";
3018
668
  case DELINEARIZATION:
3019
2
    return "Delinearization";
3020
0
  }
3021
0
  llvm_unreachable("Unknown AssumptionKind!");
3022
0
}
3023
3024
8.02k
bool Scop::isEffectiveAssumption(isl::set Set, AssumptionSign Sign) {
3025
8.02k
  if (Sign == AS_ASSUMPTION) {
3026
4.65k
    if (Context.is_subset(Set))
3027
4.47k
      return false;
3028
182
3029
182
    if (AssumedContext.is_subset(Set))
3030
48
      return false;
3031
3.37k
  } else {
3032
3.37k
    if (Set.is_disjoint(Context))
3033
2.32k
      return false;
3034
1.05k
3035
1.05k
    if (Set.is_subset(InvalidContext))
3036
518
      return false;
3037
668
  }
3038
668
  return true;
3039
668
}
3040
3041
bool Scop::trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3042
8.02k
                           AssumptionSign Sign, BasicBlock *BB) {
3043
8.02k
  if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign))
3044
7.35k
    return false;
3045
668
3046
668
  // Do never emit trivial assumptions as they only clutter the output.
3047
668
  if (!PollyRemarksMinimal) {
3048
0
    isl::set Univ;
3049
0
    if (Sign == AS_ASSUMPTION)
3050
0
      Univ = isl::set::universe(Set.get_space());
3051
0
3052
0
    bool IsTrivial = (Sign == AS_RESTRICTION && Set.is_empty()) ||
3053
0
                     (Sign == AS_ASSUMPTION && Univ.is_equal(Set));
3054
0
3055
0
    if (IsTrivial)
3056
0
      return false;
3057
668
  }
3058
668
3059
668
  switch (Kind) {
3060
668
  case ALIASING:
3061
5
    AssumptionsAliasing++;
3062
5
    break;
3063
668
  case INBOUNDS:
3064
114
    AssumptionsInbounds++;
3065
114
    break;
3066
668
  case WRAPPING:
3067
345
    AssumptionsWrapping++;
3068
345
    break;
3069
668
  case UNSIGNED:
3070
87
    AssumptionsUnsigned++;
3071
87
    break;
3072
668
  case COMPLEXITY:
3073
8
    AssumptionsComplexity++;
3074
8
    break;
3075
668
  case PROFITABLE:
3076
2
    AssumptionsUnprofitable++;
3077
2
    break;
3078
668
  case ERRORBLOCK:
3079
22
    AssumptionsErrorBlock++;
3080
22
    break;
3081
668
  case INFINITELOOP:
3082
73
    AssumptionsInfiniteLoop++;
3083
73
    break;
3084
668
  case INVARIANTLOAD:
3085
10
    AssumptionsInvariantLoad++;
3086
10
    break;
3087
668
  case DELINEARIZATION:
3088
2
    AssumptionsDelinearization++;
3089
2
    break;
3090
668
  }
3091
668
3092
668
  auto Suffix = Sign == AS_ASSUMPTION ? 
" assumption:\t"134
:
" restriction:\t"534
;
3093
668
  std::string Msg = toString(Kind) + Suffix + Set.to_str();
3094
668
  if (BB)
3095
443
    ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB)
3096
443
             << Msg);
3097
225
  else
3098
225
    ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc,
3099
225
                                        R.getEntry())
3100
225
             << Msg);
3101
668
  return true;
3102
668
}
3103
3104
void Scop::addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3105
8.02k
                         AssumptionSign Sign, BasicBlock *BB) {
3106
8.02k
  // Simplify the assumptions/restrictions first.
3107
8.02k
  Set = Set.gist_params(getContext());
3108
8.02k
3109
8.02k
  if (!trackAssumption(Kind, Set, Loc, Sign, BB))
3110
7.35k
    return;
3111
668
3112
668
  if (Sign == AS_ASSUMPTION)
3113
134
    AssumedContext = AssumedContext.intersect(Set).coalesce();
3114
534
  else
3115
534
    InvalidContext = InvalidContext.unite(Set).coalesce();
3116
668
}
3117
3118
void Scop::recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3119
8.18k
                            AssumptionSign Sign, BasicBlock *BB) {
3120
8.18k
  assert((Set.is_params() || BB) &&
3121
8.18k
         "Assumptions without a basic block must be parameter sets");
3122
8.18k
  RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB});
3123
8.18k
}
3124
3125
21
void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) {
3126
21
  LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n");
3127
21
  addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB);
3128
21
}
3129
3130
4.05k
isl::set Scop::getInvalidContext() const { return InvalidContext; }
3131
3132
489
void Scop::printContext(raw_ostream &OS) const {
3133
489
  OS << "Context:\n";
3134
489
  OS.indent(4) << Context << "\n";
3135
489
3136
489
  OS.indent(4) << "Assumed Context:\n";
3137
489
  OS.indent(4) << AssumedContext << "\n";
3138
489
3139
489
  OS.indent(4) << "Invalid Context:\n";
3140
489
  OS.indent(4) << InvalidContext << "\n";
3141
489
3142
489
  unsigned Dim = 0;
3143
489
  for (const SCEV *Parameter : Parameters)
3144
653
    OS.indent(4) << "p" << Dim++ << ": " << *Parameter << "\n";
3145
489
}
3146
3147
489
void Scop::printAliasAssumptions(raw_ostream &OS) const {
3148
489
  int noOfGroups = 0;
3149
489
  for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) {
3150
91
    if (Pair.second.size() == 0)
3151
29
      noOfGroups += 1;
3152
62
    else
3153
62
      noOfGroups += Pair.second.size();
3154
91
  }
3155
489
3156
489
  OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n";
3157
489
  if (MinMaxAliasGroups.empty()) {
3158
402
    OS.indent(8) << "n/a\n";
3159
402
    return;
3160
402
  }
3161
87
3162
91
  
for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups)87
{
3163
91
3164
91
    // If the group has no read only accesses print the write accesses.
3165
91
    if (Pair.second.empty()) {
3166
29
      OS.indent(8) << "[[";
3167
68
      for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
3168
68
        OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3169
68
           << ">";
3170
68
      }
3171
29
      OS << " ]]\n";
3172
29
    }
3173
91
3174
92
    for (const MinMaxAccessTy &MMAReadOnly : Pair.second) {
3175
92
      OS.indent(8) << "[[";
3176
92
      OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">";
3177
110
      for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
3178
110
        OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3179
110
           << ">";
3180
110
      }
3181
92
      OS << " ]]\n";
3182
92
    }
3183
91
  }
3184
87
}
3185
3186
489
void Scop::printStatements(raw_ostream &OS, bool PrintInstructions) const {
3187
489
  OS << "Statements {\n";
3188
489
3189
850
  for (const ScopStmt &Stmt : *this) {
3190
850
    OS.indent(4);
3191
850
    Stmt.print(OS, PrintInstructions);
3192
850
  }
3193
489
3194
489
  OS.indent(4) << "}\n";
3195
489
}
3196
3197
489
void Scop::printArrayInfo(raw_ostream &OS) const {
3198
489
  OS << "Arrays {\n";
3199
489
3200
489
  for (auto &Array : arrays())
3201
1.07k
    Array->print(OS);
3202
489
3203
489
  OS.indent(4) << "}\n";
3204
489
3205
489
  OS.indent(4) << "Arrays (Bounds as pw_affs) {\n";
3206
489
3207
489
  for (auto &Array : arrays())
3208
1.07k
    Array->print(OS, /* SizeAsPwAff */ true);
3209
489
3210
489
  OS.indent(4) << "}\n";
3211
489
}
3212
3213
489
void Scop::print(raw_ostream &OS, bool PrintInstructions) const {
3214
489
  OS.indent(4) << "Function: " << getFunction().getName() << "\n";
3215
489
  OS.indent(4) << "Region: " << getNameStr() << "\n";
3216
489
  OS.indent(4) << "Max Loop Depth:  " << getMaxLoopDepth() << "\n";
3217
489
  OS.indent(4) << "Invariant Accesses: {\n";
3218
489
  for (const auto &IAClass : InvariantEquivClasses) {
3219
163
    const auto &MAs = IAClass.InvariantAccesses;
3220
163
    if (MAs.empty()) {
3221
1
      OS.indent(12) << "Class Pointer: " << *IAClass.IdentifyingPointer << "\n";
3222
162
    } else {
3223
162
      MAs.front()->print(OS);
3224
162
      OS.indent(12) << "Execution Context: " << IAClass.ExecutionContext
3225
162
                    << "\n";
3226
162
    }
3227
163
  }
3228
489
  OS.indent(4) << "}\n";
3229
489
  printContext(OS.indent(4));
3230
489
  printArrayInfo(OS.indent(4));
3231
489
  printAliasAssumptions(OS);
3232
489
  printStatements(OS.indent(4), PrintInstructions);
3233
489
}
3234
3235
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3236
LLVM_DUMP_METHOD void Scop::dump() const { print(dbgs(), true); }
3237
#endif
3238
3239
33.0k
isl::ctx Scop::getIslCtx() const { return IslCtx.get(); }
3240
3241
__isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
3242
10.2k
                                 bool NonNegative) {
3243
10.2k
  // First try to use the SCEVAffinator to generate a piecewise defined
3244
10.2k
  // affine function from @p E in the context of @p BB. If that tasks becomes to
3245
10.2k
  // complex the affinator might return a nullptr. In such a case we invalidate
3246
10.2k
  // the SCoP and return a dummy value. This way we do not need to add error
3247
10.2k
  // handling code to all users of this function.
3248
10.2k
  auto PWAC = Affinator.getPwAff(E, BB);
3249
10.2k
  if (PWAC.first) {
3250
10.2k
    // TODO: We could use a heuristic and either use:
3251
10.2k
    //         SCEVAffinator::takeNonNegativeAssumption
3252
10.2k
    //       or
3253
10.2k
    //         SCEVAffinator::interpretAsUnsigned
3254
10.2k
    //       to deal with unsigned or "NonNegative" SCEVs.
3255
10.2k
    if (NonNegative)
3256
43
      Affinator.takeNonNegativeAssumption(PWAC);
3257
10.2k
    return PWAC;
3258
10.2k
  }
3259
0
3260
0
  auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
3261
0
  invalidate(COMPLEXITY, DL, BB);
3262
0
  return Affinator.getPwAff(SE->getZero(E->getType()), BB);
3263
0
}
3264
3265
12.6k
isl::union_set Scop::getDomains() const {
3266
12.6k
  isl_space *EmptySpace = isl_space_params_alloc(getIslCtx().get(), 0);
3267
12.6k
  isl_union_set *Domain = isl_union_set_empty(EmptySpace);
3268
12.6k
3269
12.6k
  for (const ScopStmt &Stmt : *this)
3270
27.4k
    Domain = isl_union_set_add_set(Domain, Stmt.getDomain().release());
3271
12.6k
3272
12.6k
  return isl::manage(Domain);
3273
12.6k
}
3274
3275
541
isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) {
3276
541
  PWACtx PWAC = getPwAff(E, BB);
3277
541
  return PWAC.first;
3278
541
}
3279
3280
isl::union_map
3281
1.34k
Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) {
3282
1.34k
  isl::union_map Accesses = isl::union_map::empty(getParamSpace());
3283
1.34k
3284
2.71k
  for (ScopStmt &Stmt : *this) {
3285
5.67k
    for (MemoryAccess *MA : Stmt) {
3286
5.67k
      if (!Predicate(*MA))
3287
586
        continue;
3288
5.08k
3289
5.08k
      isl::set Domain = Stmt.getDomain();
3290
5.08k
      isl::map AccessDomain = MA->getAccessRelation();
3291
5.08k
      AccessDomain = AccessDomain.intersect_domain(Domain);
3292
5.08k
      Accesses = Accesses.add_map(AccessDomain);
3293
5.08k
    }
3294
2.71k
  }
3295
1.34k
3296
1.34k
  return Accesses.coalesce();
3297
1.34k
}
3298
3299
7
isl::union_map Scop::getMustWrites() {
3300
23
  return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); });
3301
7
}
3302
3303
7
isl::union_map Scop::getMayWrites() {
3304
23
  return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); });
3305
7
}
3306
3307
166
isl::union_map Scop::getWrites() {
3308
903
  return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); });
3309
166
}
3310
3311
0
isl::union_map Scop::getReads() {
3312
0
  return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); });
3313
0
}
3314
3315
1.16k
isl::union_map Scop::getAccesses() {
3316
4.72k
  return getAccessesOfType([](MemoryAccess &MA) { return true; });
3317
1.16k
}
3318
3319
0
isl::union_map Scop::getAccesses(ScopArrayInfo *Array) {
3320
0
  return getAccessesOfType(
3321
0
      [Array](MemoryAccess &MA) { return MA.getScopArrayInfo() == Array; });
3322
0
}
3323
3324
1.42k
isl::union_map Scop::getSchedule() const {
3325
1.42k
  auto Tree = getScheduleTree();
3326
1.42k
  return Tree.get_map();
3327
1.42k
}
3328
3329
3.15k
isl::schedule Scop::getScheduleTree() const {
3330
3.15k
  return Schedule.intersect_domain(getDomains());
3331
3.15k
}
3332
3333
107
void Scop::setSchedule(isl::union_map NewSchedule) {
3334
107
  auto S = isl::schedule::from_domain(getDomains());
3335
107
  Schedule = S.insert_partial_schedule(
3336
107
      isl::multi_union_pw_aff::from_union_map(NewSchedule));
3337
107
  ScheduleModified = true;
3338
107
}
3339
3340
1.19k
void Scop::setScheduleTree(isl::schedule NewSchedule) {
3341
1.19k
  Schedule = NewSchedule;
3342
1.19k
  ScheduleModified = true;
3343
1.19k
}
3344
3345
7
bool Scop::restrictDomains(isl::union_set Domain) {
3346
7
  bool Changed = false;
3347
19
  for (ScopStmt &Stmt : *this) {
3348
19
    isl::union_set StmtDomain = isl::union_set(Stmt.getDomain());
3349
19
    isl::union_set NewStmtDomain = StmtDomain.intersect(Domain);
3350
19
3351
19
    if (StmtDomain.is_subset(NewStmtDomain))
3352
11
      continue;
3353
8
3354
8
    Changed = true;
3355
8
3356
8
    NewStmtDomain = NewStmtDomain.coalesce();
3357
8
3358
8
    if (NewStmtDomain.is_empty())
3359
7
      Stmt.restrictDomain(isl::set::empty(Stmt.getDomainSpace()));
3360
1
    else
3361
1
      Stmt.restrictDomain(isl::set(NewStmtDomain));
3362
8
  }
3363
7
  return Changed;
3364
7
}
3365
3366
18.9k
ScalarEvolution *Scop::getSE() const { return SE; }
3367
3368
void Scop::addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop,
3369
9.15k
                       std::vector<Instruction *> Instructions) {
3370
9.15k
  assert(BB && "Unexpected nullptr!");
3371
9.15k
  Stmts.emplace_back(*this, *BB, Name, SurroundingLoop, Instructions);
3372
9.15k
  auto *Stmt = &Stmts.back();
3373
9.15k
  StmtMap[BB].push_back(Stmt);
3374
9.15k
  for (Instruction *Inst : Instructions) {
3375
7.09k
    assert(!InstStmtMap.count(Inst) &&
3376
7.09k
           "Unexpected statement corresponding to the instruction.");
3377
7.09k
    InstStmtMap[Inst] = Stmt;
3378
7.09k
  }
3379
9.15k
}
3380
3381
void Scop::addScopStmt(Region *R, StringRef Name, Loop *SurroundingLoop,
3382
122
                       std::vector<Instruction *> Instructions) {
3383
122
  assert(R && "Unexpected nullptr!");
3384
122
  Stmts.emplace_back(*this, *R, Name, SurroundingLoop, Instructions);
3385
122
  auto *Stmt = &Stmts.back();
3386
122
3387
448
  for (Instruction *Inst : Instructions) {
3388
448
    assert(!InstStmtMap.count(Inst) &&
3389
448
           "Unexpected statement corresponding to the instruction.");
3390
448
    InstStmtMap[Inst] = Stmt;
3391
448
  }
3392
122
3393
336
  for (BasicBlock *BB : R->blocks()) {
3394
336
    StmtMap[BB].push_back(Stmt);
3395
336
    if (BB == R->getEntry())
3396
122
      continue;
3397
548
    
for (Instruction &Inst : *BB)214
{
3398
548
      assert(!InstStmtMap.count(&Inst) &&
3399
548
             "Unexpected statement corresponding to the instruction.");
3400
548
      InstStmtMap[&Inst] = Stmt;
3401
548
    }
3402
214
  }
3403
122
}
3404
3405
ScopStmt *Scop::addScopStmt(isl::map SourceRel, isl::map TargetRel,
3406
24
                            isl::set Domain) {
3407
#ifndef NDEBUG
3408
  isl::set SourceDomain = SourceRel.domain();
3409
  isl::set TargetDomain = TargetRel.domain();
3410
  assert(Domain.is_subset(TargetDomain) &&
3411
         "Target access not defined for complete statement domain");
3412
  assert(Domain.is_subset(SourceDomain) &&
3413
         "Source access not defined for complete statement domain");
3414
#endif
3415
  Stmts.emplace_back(*this, SourceRel, TargetRel, Domain);
3416
24
  CopyStmtsNum++;
3417
24
  return &(Stmts.back());
3418
24
}
3419
3420
6.33k
ArrayRef<ScopStmt *> Scop::getStmtListFor(BasicBlock *BB) const {
3421
6.33k
  auto StmtMapIt = StmtMap.find(BB);
3422
6.33k
  if (StmtMapIt == StmtMap.end())
3423
74
    return {};
3424
6.26k
  return StmtMapIt->second;
3425
6.26k
}
3426
3427
605
ScopStmt *Scop::getIncomingStmtFor(const Use &U) const {
3428
605
  auto *PHI = cast<PHINode>(U.getUser());
3429
605
  BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
3430
605
3431
605
  // If the value is a non-synthesizable from the incoming block, use the
3432
605
  // statement that contains it as user statement.
3433
605
  if (auto *IncomingInst = dyn_cast<Instruction>(U.get())) {
3434
320
    if (IncomingInst->getParent() == IncomingBB) {
3435
177
      if (ScopStmt *IncomingStmt = getStmtFor(IncomingInst))
3436
154
        return IncomingStmt;
3437
451
    }
3438
320
  }
3439
451
3440
451
  // Otherwise, use the epilogue/last statement.
3441
451
  return getLastStmtFor(IncomingBB);
3442
451
}
3443
3444
493
ScopStmt *Scop::getLastStmtFor(BasicBlock *BB) const {
3445
493
  ArrayRef<ScopStmt *> StmtList = getStmtListFor(BB);
3446
493
  if (!StmtList.empty())
3447
422
    return StmtList.back();
3448
71
  return nullptr;
3449
71
}
3450
3451
5.55k
ArrayRef<ScopStmt *> Scop::getStmtListFor(RegionNode *RN) const {
3452
5.55k
  if (RN->isSubRegion())
3453
106
    return getStmtListFor(RN->getNodeAs<Region>());
3454
5.44k
  return getStmtListFor(RN->getNodeAs<BasicBlock>());
3455
5.44k
}
3456
3457
106
ArrayRef<ScopStmt *> Scop::getStmtListFor(Region *R) const {
3458
106
  return getStmtListFor(R->getEntry());
3459
106
}
3460
3461
14.3k
int Scop::getRelativeLoopDepth(const Loop *L) const {
3462
14.3k
  if (!L || 
!R.contains(L)12.9k
)
3463
1.52k
    return -1;
3464
12.8k
  // outermostLoopInRegion always returns nullptr for top level regions
3465
12.8k
  if (R.isTopLevelRegion()) {
3466
48
    // LoopInfo's depths start at 1, we start at 0
3467
48
    return L->getLoopDepth() - 1;
3468
12.7k
  } else {
3469
12.7k
    Loop *OuterLoop = R.outermostLoopInRegion(const_cast<Loop *>(L));
3470
12.7k
    assert(OuterLoop);
3471
12.7k
    return L->getLoopDepth() - OuterLoop->getLoopDepth();
3472
12.7k
  }
3473
12.8k
}
3474
3475
259
ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) {
3476
529
  for (auto &SAI : arrays()) {
3477
529
    if (SAI->getName() == BaseName)
3478
258
      return SAI;
3479
529
  }
3480
259
  
return nullptr1
;
3481
259
}
3482
3483
4.77k
void Scop::addAccessData(MemoryAccess *Access) {
3484
4.77k
  const ScopArrayInfo *SAI = Access->getOriginalScopArrayInfo();
3485
4.77k
  assert(SAI && "can only use after access relations have been constructed");
3486
4.77k
3487
4.77k
  if (Access->isOriginalValueKind() && 
Access->isRead()683
)
3488
353
    ValueUseAccs[SAI].push_back(Access);
3489
4.42k
  else if (Access->isOriginalAnyPHIKind() && 
Access->isWrite()660
)
3490
429
    PHIIncomingAccs[SAI].push_back(Access);
3491
4.77k
}
3492
3493
527
void Scop::removeAccessData(MemoryAccess *Access) {
3494
527
  if (Access->isOriginalValueKind() && 
Access->isWrite()71
) {
3495
27
    ValueDefAccs.erase(Access->getAccessValue());
3496
500
  } else if (Access->isOriginalValueKind() && 
Access->isRead()44
) {
3497
44
    auto &Uses = ValueUseAccs[Access->getScopArrayInfo()];
3498
44
    auto NewEnd = std::remove(Uses.begin(), Uses.end(), Access);
3499
44
    Uses.erase(NewEnd, Uses.end());
3500
456
  } else if (Access->isOriginalPHIKind() && 
Access->isRead()21
) {
3501
14
    PHINode *PHI = cast<PHINode>(Access->getAccessInstruction());
3502
14
    PHIReadAccs.erase(PHI);
3503
442
  } else if (Access->isOriginalAnyPHIKind() && 
Access->isWrite()7
) {
3504
7
    auto &Incomings = PHIIncomingAccs[Access->getScopArrayInfo()];
3505
7
    auto NewEnd = std::remove(Incomings.begin(), Incomings.end(), Access);
3506
7
    Incomings.erase(NewEnd, Incomings.end());
3507
7
  }
3508
527
}
3509
3510
295
MemoryAccess *Scop::getValueDef(const ScopArrayInfo *SAI) const {
3511
295
  assert(SAI->isValueKind());
3512
295
3513
295
  Instruction *Val = dyn_cast<Instruction>(SAI->getBasePtr());
3514
295
  if (!Val)
3515
3
    return nullptr;
3516
292
3517
292
  return ValueDefAccs.lookup(Val);
3518
292
}
3519
3520
110
ArrayRef<MemoryAccess *> Scop::getValueUses(const ScopArrayInfo *SAI) const {
3521
110
  assert(SAI->isValueKind());
3522
110
  auto It = ValueUseAccs.find(SAI);
3523
110
  if (It == ValueUseAccs.end())
3524
0
    return {};
3525
110
  return It->second;
3526
110
}
3527
3528
196
MemoryAccess *Scop::getPHIRead(const ScopArrayInfo *SAI) const {
3529
196
  assert(SAI->isPHIKind() || SAI->isExitPHIKind());
3530
196
3531
196
  if (SAI->isExitPHIKind())
3532
0
    return nullptr;
3533
196
3534
196
  PHINode *PHI = cast<PHINode>(SAI->getBasePtr());
3535
196
  return PHIReadAccs.lookup(PHI);
3536
196
}
3537
3538
242
ArrayRef<MemoryAccess *> Scop::getPHIIncomings(const ScopArrayInfo *SAI) const {
3539
242
  assert(SAI->isPHIKind() || SAI->isExitPHIKind());
3540
242
  auto It = PHIIncomingAccs.find(SAI);
3541
242
  if (It == PHIIncomingAccs.end())
3542
0
    return {};
3543
242
  return It->second;
3544
242
}
3545
3546
21.9k
bool Scop::isEscaping(Instruction *Inst) {
3547
21.9k
  assert(contains(Inst) && "The concept of escaping makes only sense for "
3548
21.9k
                           "values defined inside the SCoP");
3549
21.9k
3550
21.9k
  for (Use &Use : Inst->uses()) {
3551
19.1k
    BasicBlock *UserBB = getUseBlock(Use);
3552
19.1k
    if (!contains(UserBB))
3553
62
      return true;
3554
19.0k
3555
19.0k
    // When the SCoP region exit needs to be simplified, PHIs in the region exit
3556
19.0k
    // move to a new basic block such that its incoming blocks are not in the
3557
19.0k
    // SCoP anymore.
3558
19.0k
    if (hasSingleExitEdge() && 
isa<PHINode>(Use.getUser())16.4k
&&
3559
19.0k
        
isExit(cast<PHINode>(Use.getUser())->getParent())1.84k
)
3560
34
      return true;
3561
19.0k
  }
3562
21.9k
  
return false21.8k
;
3563
21.9k
}
3564
3565
204
void Scop::incrementNumberOfAliasingAssumptions(unsigned step) {
3566
204
  AssumptionsAliasing += step;
3567
204
}
3568
3569
930
Scop::ScopStatistics Scop::getStatistics() const {
3570
930
  ScopStatistics Result;
3571
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
3572
  auto LoopStat = ScopDetection::countBeneficialLoops(&R, *SE, *getLI(), 0);
3573
3574
  int NumTotalLoops = LoopStat.NumLoops;
3575
  Result.NumBoxedLoops = getBoxedLoops().size();
3576
  Result.NumAffineLoops = NumTotalLoops - Result.NumBoxedLoops;
3577
3578
  for (const ScopStmt &Stmt : *this) {
3579
    isl::set Domain = Stmt.getDomain().intersect_params(getContext());
3580
    bool IsInLoop = Stmt.getNumIterators() >= 1;
3581
    for (MemoryAccess *MA : Stmt) {
3582
      if (!MA->isWrite())
3583
        continue;
3584
3585
      if (MA->isLatestValueKind()) {
3586
        Result.NumValueWrites += 1;
3587
        if (IsInLoop)
3588
          Result.NumValueWritesInLoops += 1;
3589
      }
3590
3591
      if (MA->isLatestAnyPHIKind()) {
3592
        Result.NumPHIWrites += 1;
3593
        if (IsInLoop)
3594
          Result.NumPHIWritesInLoops += 1;
3595
      }
3596
3597
      isl::set AccSet =
3598
          MA->getAccessRelation().intersect_domain(Domain).range();
3599
      if (AccSet.is_singleton()) {
3600
        Result.NumSingletonWrites += 1;
3601
        if (IsInLoop)
3602
          Result.NumSingletonWritesInLoops += 1;
3603
      }
3604
    }
3605
  }
3606
#endif
3607
  return Result;
3608
930
}
3609
3610
42
raw_ostream &polly::operator<<(raw_ostream &OS, const Scop &scop) {
3611
42
  scop.print(OS, PollyPrintInstructions);
3612
42
  return OS;
3613
42
}
3614
3615
//===----------------------------------------------------------------------===//
3616
1.13k
void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const {
3617
1.13k
  AU.addRequired<LoopInfoWrapperPass>();
3618
1.13k
  AU.addRequired<RegionInfoPass>();
3619
1.13k
  AU.addRequired<DominatorTreeWrapperPass>();
3620
1.13k
  AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
3621
1.13k
  AU.addRequiredTransitive<ScopDetectionWrapperPass>();
3622
1.13k
  AU.addRequired<AAResultsWrapperPass>();
3623
1.13k
  AU.addRequired<AssumptionCacheTracker>();
3624
1.13k
  AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
3625
1.13k
  AU.setPreservesAll();
3626
1.13k
}
3627
3628
void updateLoopCountStatistic(ScopDetection::LoopStats Stats,
3629
0
                              Scop::ScopStatistics ScopStats) {
3630
0
  assert(Stats.NumLoops == ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops);
3631
0
3632
0
  NumScops++;
3633
0
  NumLoopsInScop += Stats.NumLoops;
3634
0
  MaxNumLoopsInScop =
3635
0
      std::max(MaxNumLoopsInScop.getValue(), (unsigned)Stats.NumLoops);
3636
0
3637
0
  if (Stats.MaxDepth == 0)
3638
0
    NumScopsDepthZero++;
3639
0
  else if (Stats.MaxDepth == 1)
3640
0
    NumScopsDepthOne++;
3641
0
  else if (Stats.MaxDepth == 2)
3642
0
    NumScopsDepthTwo++;
3643
0
  else if (Stats.MaxDepth == 3)
3644
0
    NumScopsDepthThree++;
3645
0
  else if (Stats.MaxDepth == 4)
3646
0
    NumScopsDepthFour++;
3647
0
  else if (Stats.MaxDepth == 5)
3648
0
    NumScopsDepthFive++;
3649
0
  else
3650
0
    NumScopsDepthLarger++;
3651
0
3652
0
  NumAffineLoops += ScopStats.NumAffineLoops;
3653
0
  NumBoxedLoops += ScopStats.NumBoxedLoops;
3654
0
3655
0
  NumValueWrites += ScopStats.NumValueWrites;
3656
0
  NumValueWritesInLoops += ScopStats.NumValueWritesInLoops;
3657
0
  NumPHIWrites += ScopStats.NumPHIWrites;
3658
0
  NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops;
3659
0
  NumSingletonWrites += ScopStats.NumSingletonWrites;
3660
0
  NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops;
3661
0
}
3662
3663
4.29k
bool ScopInfoRegionPass::runOnRegion(Region *R, RGPassManager &RGM) {
3664
4.29k
  auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD();
3665
4.29k
3666
4.29k
  if (!SD.isMaxRegionInScop(*R))
3667
3.13k
    return false;
3668
1.15k
3669
1.15k
  Function *F = R->getEntry()->getParent();
3670
1.15k
  auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
3671
1.15k
  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
3672
1.15k
  auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
3673
1.15k
  auto const &DL = F->getParent()->getDataLayout();
3674
1.15k
  auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
3675
1.15k
  auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F);
3676
1.15k
  auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
3677
1.15k
3678
1.15k
  ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE);
3679
1.15k
  S = SB.getScop(); // take ownership of scop object
3680
1.15k
3681
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
3682
  if (S) {
3683
    ScopDetection::LoopStats Stats =
3684
        ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
3685
    updateLoopCountStatistic(Stats, S->getStatistics());
3686
  }
3687
#endif
3688
3689
1.15k
  return false;
3690
1.15k
}
3691
3692
1.52k
void ScopInfoRegionPass::print(raw_ostream &OS, const Module *) const {
3693
1.52k
  if (S)
3694
409
    S->print(OS, PollyPrintInstructions);
3695
1.11k
  else
3696
1.11k
    OS << "Invalid Scop!\n";
3697
1.52k
}
3698
3699
char ScopInfoRegionPass::ID = 0;
3700
3701
0
Pass *polly::createScopInfoRegionPassPass() { return new ScopInfoRegionPass(); }
3702
3703
48.2k
INITIALIZE_PASS_BEGIN(ScopInfoRegionPass, "polly-scops",
3704
48.2k
                      "Polly - Create polyhedral description of Scops", false,
3705
48.2k
                      false);
3706
48.2k
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
3707
48.2k
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker);
3708
48.2k
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
3709
48.2k
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
3710
48.2k
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
3711
48.2k
INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
3712
48.2k
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
3713
48.2k
INITIALIZE_PASS_END(ScopInfoRegionPass, "polly-scops",
3714
                    "Polly - Create polyhedral description of Scops", false,
3715
                    false)
3716
3717
//===----------------------------------------------------------------------===//
3718
ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE,
3719
                   LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT,
3720
                   AssumptionCache &AC, OptimizationRemarkEmitter &ORE)
3721
50
    : DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) {
3722
50
  recompute();
3723
50
}
3724
3725
50
void ScopInfo::recompute() {
3726
50
  RegionToScopMap.clear();
3727
50
  /// Create polyhedral description of scops for all the valid regions of a
3728
50
  /// function.
3729
50
  for (auto &It : SD) {
3730
49
    Region *R = const_cast<Region *>(It);
3731
49
    if (!SD.isMaxRegionInScop(*R))
3732
0
      continue;
3733
49
3734
49
    ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE);
3735
49
    std::unique_ptr<Scop> S = SB.getScop();
3736
49
    if (!S)
3737
3
      continue;
3738
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
3739
    ScopDetection::LoopStats Stats =
3740
        ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
3741
    updateLoopCountStatistic(Stats, S->getStatistics());
3742
#endif
3743
46
    bool Inserted = RegionToScopMap.insert({R, std::move(S)}).second;
3744
46
    assert(Inserted && "Building Scop for the same region twice!");
3745
46
    (void)Inserted;
3746
46
  }
3747
50
}
3748
3749
bool ScopInfo::invalidate(Function &F, const PreservedAnalyses &PA,
3750
0
                          FunctionAnalysisManager::Invalidator &Inv) {
3751
0
  // Check whether the analysis, all analyses on functions have been preserved
3752
0
  // or anything we're holding references to is being invalidated
3753
0
  auto PAC = PA.getChecker<ScopInfoAnalysis>();
3754
0
  return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
3755
0
         Inv.invalidate<ScopAnalysis>(F, PA) ||
3756
0
         Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
3757
0
         Inv.invalidate<LoopAnalysis>(F, PA) ||
3758
0
         Inv.invalidate<AAManager>(F, PA) ||
3759
0
         Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
3760
0
         Inv.invalidate<AssumptionAnalysis>(F, PA);
3761
0
}
3762
3763
AnalysisKey ScopInfoAnalysis::Key;
3764
3765
ScopInfoAnalysis::Result ScopInfoAnalysis::run(Function &F,
3766
1
                                               FunctionAnalysisManager &FAM) {
3767
1
  auto &SD = FAM.getResult<ScopAnalysis>(F);
3768
1
  auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
3769
1
  auto &LI = FAM.getResult<LoopAnalysis>(F);
3770
1
  auto &AA = FAM.getResult<AAManager>(F);
3771
1
  auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
3772
1
  auto &AC = FAM.getResult<AssumptionAnalysis>(F);
3773
1
  auto &DL = F.getParent()->getDataLayout();
3774
1
  auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
3775
1
  return {DL, SD, SE, LI, AA, DT, AC, ORE};
3776
1
}
3777
3778
PreservedAnalyses ScopInfoPrinterPass::run(Function &F,
3779
0
                                           FunctionAnalysisManager &FAM) {
3780
0
  auto &SI = FAM.getResult<ScopInfoAnalysis>(F);
3781
0
  // Since the legacy PM processes Scops in bottom up, we print them in reverse
3782
0
  // order here to keep the output persistent
3783
0
  for (auto &It : reverse(SI)) {
3784
0
    if (It.second)
3785
0
      It.second->print(Stream, PollyPrintInstructions);
3786
0
    else
3787
0
      Stream << "Invalid Scop!\n";
3788
0
  }
3789
0
  return PreservedAnalyses::all();
3790
0
}
3791
3792
44
void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
3793
44
  AU.addRequired<LoopInfoWrapperPass>();
3794
44
  AU.addRequired<RegionInfoPass>();
3795
44
  AU.addRequired<DominatorTreeWrapperPass>();
3796
44
  AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
3797
44
  AU.addRequiredTransitive<ScopDetectionWrapperPass>();
3798
44
  AU.addRequired<AAResultsWrapperPass>();
3799
44
  AU.addRequired<AssumptionCacheTracker>();
3800
44
  AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
3801
44
  AU.setPreservesAll();
3802
44
}
3803
3804
49
bool ScopInfoWrapperPass::runOnFunction(Function &F) {
3805
49
  auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD();
3806
49
  auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
3807
49
  auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
3808
49
  auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
3809
49
  auto const &DL = F.getParent()->getDataLayout();
3810
49
  auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
3811
49
  auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
3812
49
  auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
3813
49
3814
49
  Result.reset(new ScopInfo{DL, SD, SE, LI, AA, DT, AC, ORE});
3815
49
  return false;
3816
49
}
3817
3818
23
void ScopInfoWrapperPass::print(raw_ostream &OS, const Module *) const {
3819
23
  for (auto &It : *Result) {
3820
21
    if (It.second)
3821
21
      It.second->print(OS, PollyPrintInstructions);
3822
0
    else
3823
0
      OS << "Invalid Scop!\n";
3824
21
  }
3825
23
}
3826
3827
char ScopInfoWrapperPass::ID = 0;
3828
3829
0
Pass *polly::createScopInfoWrapperPassPass() {
3830
0
  return new ScopInfoWrapperPass();
3831
0
}
3832
3833
48.2k
INITIALIZE_PASS_BEGIN(
3834
48.2k
    ScopInfoWrapperPass, "polly-function-scops",
3835
48.2k
    "Polly - Create polyhedral description of all Scops of a function", false,
3836
48.2k
    false);
3837
48.2k
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
3838
48.2k
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker);
3839
48.2k
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
3840
48.2k
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
3841
48.2k
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
3842
48.2k
INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
3843
48.2k
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
3844
48.2k
INITIALIZE_PASS_END(
3845
    ScopInfoWrapperPass, "polly-function-scops",
3846
    "Polly - Create polyhedral description of all Scops of a function", false,
3847
    false)