Polly 22.0.0git
ScopBuilder.cpp
Go to the documentation of this file.
1//===- ScopBuilder.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//===----------------------------------------------------------------------===//
15
16#include "polly/ScopBuilder.h"
17#include "polly/Options.h"
18#include "polly/ScopDetection.h"
19#include "polly/ScopInfo.h"
25#include "llvm/ADT/ArrayRef.h"
26#include "llvm/ADT/EquivalenceClasses.h"
27#include "llvm/ADT/PostOrderIterator.h"
28#include "llvm/ADT/Sequence.h"
29#include "llvm/ADT/SmallSet.h"
30#include "llvm/ADT/Statistic.h"
31#include "llvm/Analysis/AliasAnalysis.h"
32#include "llvm/Analysis/AssumptionCache.h"
33#include "llvm/Analysis/Delinearization.h"
34#include "llvm/Analysis/Loads.h"
35#include "llvm/Analysis/LoopInfo.h"
36#include "llvm/Analysis/OptimizationRemarkEmitter.h"
37#include "llvm/Analysis/RegionInfo.h"
38#include "llvm/Analysis/RegionIterator.h"
39#include "llvm/Analysis/ScalarEvolution.h"
40#include "llvm/Analysis/ScalarEvolutionExpressions.h"
41#include "llvm/IR/BasicBlock.h"
42#include "llvm/IR/DataLayout.h"
43#include "llvm/IR/DebugLoc.h"
44#include "llvm/IR/DerivedTypes.h"
45#include "llvm/IR/Dominators.h"
46#include "llvm/IR/Function.h"
47#include "llvm/IR/InstrTypes.h"
48#include "llvm/IR/Instruction.h"
49#include "llvm/IR/Instructions.h"
50#include "llvm/IR/Type.h"
51#include "llvm/IR/Use.h"
52#include "llvm/IR/Value.h"
53#include "llvm/Support/CommandLine.h"
54#include "llvm/Support/Compiler.h"
55#include "llvm/Support/Debug.h"
56#include "llvm/Support/ErrorHandling.h"
57#include "llvm/Support/raw_ostream.h"
58#include <cassert>
59#include <deque>
60
61using namespace llvm;
62using namespace polly;
63
65#define DEBUG_TYPE "polly-scops"
66
67STATISTIC(ScopFound, "Number of valid Scops");
68STATISTIC(RichScopFound, "Number of Scops containing a loop");
69STATISTIC(InfeasibleScops,
70 "Number of SCoPs with statically infeasible context.");
71
73
74// The maximal number of dimensions we allow during invariant load construction.
75// More complex access ranges will result in very high compile time and are also
76// unlikely to result in good code. This value is very high and should only
77// trigger for corner cases (e.g., the "dct_luma" function in h264, SPEC2006).
78static unsigned const MaxDimensionsInAccessRange = 9;
79
80static cl::opt<bool, true> XModelReadOnlyScalars(
81 "polly-analyze-read-only-scalars",
82 cl::desc("Model read-only scalar values in the scop description"),
83 cl::location(ModelReadOnlyScalars), cl::Hidden, cl::init(true),
84 cl::cat(PollyCategory));
85
86static cl::opt<int>
87 OptComputeOut("polly-analysis-computeout",
88 cl::desc("Bound the scop analysis by a maximal amount of "
89 "computational steps (0 means no bound)"),
90 cl::Hidden, cl::init(800000), cl::cat(PollyCategory));
91
93 "polly-allow-dereference-of-all-function-parameters",
94 cl::desc(
95 "Treat all parameters to functions that are pointers as dereferencible."
96 " This is useful for invariant load hoisting, since we can generate"
97 " less runtime checks. This is only valid if all pointers to functions"
98 " are always initialized, so that Polly can choose to hoist"
99 " their loads. "),
100 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
101
102static cl::opt<bool>
103 PollyIgnoreInbounds("polly-ignore-inbounds",
104 cl::desc("Do not take inbounds assumptions at all"),
105 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
106
107static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup(
108 "polly-rtc-max-arrays-per-group",
109 cl::desc("The maximal number of arrays to compare in each alias group."),
110 cl::Hidden, cl::init(20), cl::cat(PollyCategory));
111
112static cl::opt<unsigned> RunTimeChecksMaxAccessDisjuncts(
113 "polly-rtc-max-array-disjuncts",
114 cl::desc("The maximal number of disjunts allowed in memory accesses to "
115 "to build RTCs."),
116 cl::Hidden, cl::init(8), cl::cat(PollyCategory));
117
118static cl::opt<unsigned> RunTimeChecksMaxParameters(
119 "polly-rtc-max-parameters",
120 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden,
121 cl::init(8), cl::cat(PollyCategory));
122
123static cl::opt<bool> UnprofitableScalarAccs(
124 "polly-unprofitable-scalar-accs",
125 cl::desc("Count statements with scalar accesses as not optimizable"),
126 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
127
128static cl::opt<std::string> UserContextStr(
129 "polly-context", cl::value_desc("isl parameter set"),
130 cl::desc("Provide additional constraints on the context parameters"),
131 cl::init(""), cl::cat(PollyCategory));
132
133static cl::opt<bool> DetectReductions("polly-detect-reductions",
134 cl::desc("Detect and exploit reductions"),
135 cl::Hidden, cl::init(true),
136 cl::cat(PollyCategory));
137
138// Multiplicative reductions can be disabled separately as these kind of
139// operations can overflow easily. Additive reductions and bit operations
140// are in contrast pretty stable.
142 "polly-disable-multiplicative-reductions",
143 cl::desc("Disable multiplicative reductions"), cl::Hidden,
144 cl::cat(PollyCategory));
145
147
148static cl::opt<GranularityChoice> StmtGranularity(
149 "polly-stmt-granularity",
150 cl::desc(
151 "Algorithm to use for splitting basic blocks into multiple statements"),
152 cl::values(clEnumValN(GranularityChoice::BasicBlocks, "bb",
153 "One statement per basic block"),
154 clEnumValN(GranularityChoice::ScalarIndependence, "scalar-indep",
155 "Scalar independence heuristic"),
156 clEnumValN(GranularityChoice::Stores, "store",
157 "Store-level granularity")),
159
160/// Helper to treat non-affine regions and basic blocks the same.
161///
162///{
163
164/// Return the block that is the representing block for @p RN.
165static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) {
166 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry()
167 : RN->getNodeAs<BasicBlock>();
168}
169
170/// Return the @p idx'th block that is executed after @p RN.
171static inline BasicBlock *
172getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx) {
173 if (RN->isSubRegion()) {
174 assert(idx == 0);
175 return RN->getNodeAs<Region>()->getExit();
176 }
177 return TI->getSuccessor(idx);
178}
179
180static bool containsErrorBlock(RegionNode *RN, const Region &R,
181 ScopDetection *SD) {
182 if (!RN->isSubRegion())
183 return SD->isErrorBlock(*RN->getNodeAs<BasicBlock>(), R);
184 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
185 if (SD->isErrorBlock(*BB, R))
186 return true;
187 return false;
188}
189
190///}
191
192/// Create a map to map from a given iteration to a subsequent iteration.
193///
194/// This map maps from SetSpace -> SetSpace where the dimensions @p Dim
195/// is incremented by one and all other dimensions are equal, e.g.,
196/// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3]
197///
198/// if @p Dim is 2 and @p SetSpace has 4 dimensions.
199static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim) {
200 isl::space MapSpace = SetSpace.map_from_set();
201 isl::map NextIterationMap = isl::map::universe(MapSpace);
202 for (unsigned u : rangeIslSize(0, NextIterationMap.domain_tuple_dim()))
203 if (u != Dim)
204 NextIterationMap =
205 NextIterationMap.equate(isl::dim::in, u, isl::dim::out, u);
208 C = C.set_constant_si(1);
209 C = C.set_coefficient_si(isl::dim::in, Dim, 1);
210 C = C.set_coefficient_si(isl::dim::out, Dim, -1);
211 NextIterationMap = NextIterationMap.add_constraint(C);
212 return NextIterationMap;
213}
214
215/// Add @p BSet to set @p BoundedParts if @p BSet is bounded.
217 isl::set BoundedParts = isl::set::empty(S.get_space());
218 for (isl::basic_set BSet : S.get_basic_set_list())
219 if (BSet.is_bounded())
220 BoundedParts = BoundedParts.unite(isl::set(BSet));
221 return BoundedParts;
222}
223
224/// Compute the (un)bounded parts of @p S wrt. to dimension @p Dim.
225///
226/// @returns A separation of @p S into first an unbounded then a bounded subset,
227/// both with regards to the dimension @p Dim.
228static std::pair<isl::set, isl::set> partitionSetParts(isl::set S,
229 unsigned Dim) {
230 for (unsigned u : rangeIslSize(0, S.tuple_dim()))
231 S = S.lower_bound_si(isl::dim::set, u, 0);
232
233 unsigned NumDimsS = unsignedFromIslSize(S.tuple_dim());
234 isl::set OnlyDimS = S;
235
236 // Remove dimensions that are greater than Dim as they are not interesting.
237 assert(NumDimsS >= Dim + 1);
238 OnlyDimS = OnlyDimS.project_out(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
239
240 // Create artificial parametric upper bounds for dimensions smaller than Dim
241 // as we are not interested in them.
242 OnlyDimS = OnlyDimS.insert_dims(isl::dim::param, 0, Dim);
243
244 for (unsigned u = 0; u < Dim; u++) {
246 isl::local_space(OnlyDimS.get_space()));
247 C = C.set_coefficient_si(isl::dim::param, u, 1);
248 C = C.set_coefficient_si(isl::dim::set, u, -1);
249 OnlyDimS = OnlyDimS.add_constraint(C);
250 }
251
252 // Collect all bounded parts of OnlyDimS.
253 isl::set BoundedParts = collectBoundedParts(OnlyDimS);
254
255 // Create the dimensions greater than Dim again.
256 BoundedParts =
257 BoundedParts.insert_dims(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
258
259 // Remove the artificial upper bound parameters again.
260 BoundedParts = BoundedParts.remove_dims(isl::dim::param, 0, Dim);
261
262 isl::set UnboundedParts = S.subtract(BoundedParts);
263 return std::make_pair(UnboundedParts, BoundedParts);
264}
265
266/// Create the conditions under which @p L @p Pred @p R is true.
267static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L,
268 isl::pw_aff R) {
269 switch (Pred) {
270 case ICmpInst::ICMP_EQ:
271 return L.eq_set(R);
272 case ICmpInst::ICMP_NE:
273 return L.ne_set(R);
274 case ICmpInst::ICMP_SLT:
275 return L.lt_set(R);
276 case ICmpInst::ICMP_SLE:
277 return L.le_set(R);
278 case ICmpInst::ICMP_SGT:
279 return L.gt_set(R);
280 case ICmpInst::ICMP_SGE:
281 return L.ge_set(R);
282 case ICmpInst::ICMP_ULT:
283 return L.lt_set(R);
284 case ICmpInst::ICMP_UGT:
285 return L.gt_set(R);
286 case ICmpInst::ICMP_ULE:
287 return L.le_set(R);
288 case ICmpInst::ICMP_UGE:
289 return L.ge_set(R);
290 default:
291 llvm_unreachable("Non integer predicate not supported");
292 }
293}
294
296 Loop *NewL) {
297 // If the loops are the same there is nothing to do.
298 if (NewL == OldL)
299 return Dom;
300
301 int OldDepth = scop->getRelativeLoopDepth(OldL);
302 int NewDepth = scop->getRelativeLoopDepth(NewL);
303 // If both loops are non-affine loops there is nothing to do.
304 if (OldDepth == -1 && NewDepth == -1)
305 return Dom;
306
307 // Distinguish three cases:
308 // 1) The depth is the same but the loops are not.
309 // => One loop was left one was entered.
310 // 2) The depth increased from OldL to NewL.
311 // => One loop was entered, none was left.
312 // 3) The depth decreased from OldL to NewL.
313 // => Loops were left were difference of the depths defines how many.
314 if (OldDepth == NewDepth) {
315 assert(OldL->getParentLoop() == NewL->getParentLoop());
316 Dom = Dom.project_out(isl::dim::set, NewDepth, 1);
317 Dom = Dom.add_dims(isl::dim::set, 1);
318 } else if (OldDepth < NewDepth) {
319 assert(OldDepth + 1 == NewDepth);
320 auto &R = scop->getRegion();
321 (void)R;
322 assert(NewL->getParentLoop() == OldL ||
323 ((!OldL || !R.contains(OldL)) && R.contains(NewL)));
324 Dom = Dom.add_dims(isl::dim::set, 1);
325 } else {
326 assert(OldDepth > NewDepth);
327 unsigned Diff = OldDepth - NewDepth;
328 unsigned NumDim = unsignedFromIslSize(Dom.tuple_dim());
329 assert(NumDim >= Diff);
330 Dom = Dom.project_out(isl::dim::set, NumDim - Diff, Diff);
331 }
332
333 return Dom;
334}
335
336/// Compute the isl representation for the SCEV @p E in this BB.
337///
338/// @param BB The BB for which isl representation is to be
339/// computed.
340/// @param InvalidDomainMap A map of BB to their invalid domains.
341/// @param E The SCEV that should be translated.
342/// @param NonNegative Flag to indicate the @p E has to be non-negative.
343///
344/// Note that this function will also adjust the invalid context accordingly.
345
348 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
349 const SCEV *E, bool NonNegative) {
350 PWACtx PWAC = scop->getPwAff(E, BB, NonNegative, &RecordedAssumptions);
351 InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
352 return PWAC.first.release();
353}
354
355/// Build condition sets for unsigned ICmpInst(s).
356/// Special handling is required for unsigned operands to ensure that if
357/// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst
358/// it should wrap around.
359///
360/// @param IsStrictUpperBound holds information on the predicate relation
361/// between TestVal and UpperBound, i.e,
362/// TestVal < UpperBound OR TestVal <= UpperBound
364 BasicBlock *BB, Value *Condition, __isl_keep isl_set *Domain,
365 const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound,
366 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
367 bool IsStrictUpperBound) {
368 // Do not take NonNeg assumption on TestVal
369 // as it might have MSB (Sign bit) set.
370 isl_pw_aff *TestVal = getPwAff(BB, InvalidDomainMap, SCEV_TestVal, false);
371 // Take NonNeg assumption on UpperBound.
372 isl_pw_aff *UpperBound =
373 getPwAff(BB, InvalidDomainMap, SCEV_UpperBound, true);
374
375 // 0 <= TestVal
376 isl_set *First =
379 isl_pw_aff_copy(TestVal));
380
381 isl_set *Second;
382 if (IsStrictUpperBound)
383 // TestVal < UpperBound
384 Second = isl_pw_aff_lt_set(TestVal, UpperBound);
385 else
386 // TestVal <= UpperBound
387 Second = isl_pw_aff_le_set(TestVal, UpperBound);
388
389 isl_set *ConsequenceCondSet = isl_set_intersect(First, Second);
390 return ConsequenceCondSet;
391}
392
394 BasicBlock *BB, SwitchInst *SI, Loop *L, __isl_keep isl_set *Domain,
395 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
396 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
397 Value *Condition = getConditionFromTerminator(SI);
398 assert(Condition && "No condition for switch");
399
400 isl_pw_aff *LHS, *RHS;
401 LHS = getPwAff(BB, InvalidDomainMap, SE.getSCEVAtScope(Condition, L));
402
403 unsigned NumSuccessors = SI->getNumSuccessors();
404 ConditionSets.resize(NumSuccessors);
405 for (auto &Case : SI->cases()) {
406 unsigned Idx = Case.getSuccessorIndex();
407 ConstantInt *CaseValue = Case.getCaseValue();
408
409 RHS = getPwAff(BB, InvalidDomainMap, SE.getSCEV(CaseValue));
410 isl_set *CaseConditionSet =
411 buildConditionSet(ICmpInst::ICMP_EQ, isl::manage_copy(LHS),
412 isl::manage(RHS))
413 .release();
414 ConditionSets[Idx] = isl_set_coalesce(
415 isl_set_intersect(CaseConditionSet, isl_set_copy(Domain)));
416 }
417
418 assert(ConditionSets[0] == nullptr && "Default condition set was set");
419 isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]);
420 for (unsigned u = 2; u < NumSuccessors; u++)
421 ConditionSetUnion =
422 isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u]));
423 ConditionSets[0] = isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion);
424
425 isl_pw_aff_free(LHS);
426
427 return true;
428}
429
431 BasicBlock *BB, Value *Condition, Instruction *TI, Loop *L,
433 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
434 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
435 isl_set *ConsequenceCondSet = nullptr;
436
437 if (auto Load = dyn_cast<LoadInst>(Condition)) {
438 const SCEV *LHSSCEV = SE.getSCEVAtScope(Load, L);
439 const SCEV *RHSSCEV = SE.getZero(LHSSCEV->getType());
440 bool NonNeg = false;
441 isl_pw_aff *LHS = getPwAff(BB, InvalidDomainMap, LHSSCEV, NonNeg);
442 isl_pw_aff *RHS = getPwAff(BB, InvalidDomainMap, RHSSCEV, NonNeg);
443 ConsequenceCondSet = buildConditionSet(ICmpInst::ICMP_SLE, isl::manage(LHS),
444 isl::manage(RHS))
445 .release();
446 } else if (auto *PHI = dyn_cast<PHINode>(Condition)) {
447 auto *Unique = dyn_cast<ConstantInt>(
448 getUniqueNonErrorValue(PHI, &scop->getRegion(), &SD));
449 assert(Unique &&
450 "A PHINode condition should only be accepted by ScopDetection if "
451 "getUniqueNonErrorValue returns non-NULL");
452
453 if (Unique->isZero())
454 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
455 else
456 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
457 } else if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
458 if (CCond->isZero())
459 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
460 else
461 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
462 } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
463 auto Opcode = BinOp->getOpcode();
464 assert(Opcode == Instruction::And || Opcode == Instruction::Or);
465
466 bool Valid = buildConditionSets(BB, BinOp->getOperand(0), TI, L, Domain,
467 InvalidDomainMap, ConditionSets) &&
468 buildConditionSets(BB, BinOp->getOperand(1), TI, L, Domain,
469 InvalidDomainMap, ConditionSets);
470 if (!Valid) {
471 while (!ConditionSets.empty())
472 isl_set_free(ConditionSets.pop_back_val());
473 return false;
474 }
475
476 isl_set_free(ConditionSets.pop_back_val());
477 isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
478 isl_set_free(ConditionSets.pop_back_val());
479 isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
480
481 if (Opcode == Instruction::And)
482 ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1);
483 else
484 ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1);
485 } else {
486 auto *ICond = dyn_cast<ICmpInst>(Condition);
487 assert(ICond &&
488 "Condition of exiting branch was neither constant nor ICmp!");
489
490 Region &R = scop->getRegion();
491
492 isl_pw_aff *LHS, *RHS;
493 // For unsigned comparisons we assumed the signed bit of neither operand
494 // to be set. The comparison is equal to a signed comparison under this
495 // assumption.
496 bool NonNeg = ICond->isUnsigned();
497 const SCEV *LeftOperand = SE.getSCEVAtScope(ICond->getOperand(0), L),
498 *RightOperand = SE.getSCEVAtScope(ICond->getOperand(1), L);
499
500 LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, &SD);
501 RightOperand = tryForwardThroughPHI(RightOperand, R, SE, &SD);
502
503 switch (ICond->getPredicate()) {
504 case ICmpInst::ICMP_ULT:
505 ConsequenceCondSet =
506 buildUnsignedConditionSets(BB, Condition, Domain, LeftOperand,
507 RightOperand, InvalidDomainMap, true);
508 break;
509 case ICmpInst::ICMP_ULE:
510 ConsequenceCondSet =
511 buildUnsignedConditionSets(BB, Condition, Domain, LeftOperand,
512 RightOperand, InvalidDomainMap, false);
513 break;
514 case ICmpInst::ICMP_UGT:
515 ConsequenceCondSet =
516 buildUnsignedConditionSets(BB, Condition, Domain, RightOperand,
517 LeftOperand, InvalidDomainMap, true);
518 break;
519 case ICmpInst::ICMP_UGE:
520 ConsequenceCondSet =
521 buildUnsignedConditionSets(BB, Condition, Domain, RightOperand,
522 LeftOperand, InvalidDomainMap, false);
523 break;
524 default:
525 LHS = getPwAff(BB, InvalidDomainMap, LeftOperand, NonNeg);
526 RHS = getPwAff(BB, InvalidDomainMap, RightOperand, NonNeg);
527 ConsequenceCondSet = buildConditionSet(ICond->getPredicate(),
528 isl::manage(LHS), isl::manage(RHS))
529 .release();
530 break;
531 }
532 }
533
534 // If no terminator was given we are only looking for parameter constraints
535 // under which @p Condition is true/false.
536 if (!TI)
537 ConsequenceCondSet = isl_set_params(ConsequenceCondSet);
538 assert(ConsequenceCondSet);
539 ConsequenceCondSet = isl_set_coalesce(
540 isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain)));
541
542 isl_set *AlternativeCondSet = nullptr;
543 bool TooComplex =
544 isl_set_n_basic_set(ConsequenceCondSet) >= (int)MaxDisjunctsInDomain;
545
546 if (!TooComplex) {
547 AlternativeCondSet = isl_set_subtract(isl_set_copy(Domain),
548 isl_set_copy(ConsequenceCondSet));
549 TooComplex =
550 isl_set_n_basic_set(AlternativeCondSet) >= (int)MaxDisjunctsInDomain;
551 }
552
553 if (TooComplex) {
554 scop->invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc(),
555 TI ? TI->getParent() : nullptr /* BasicBlock */);
556 isl_set_free(AlternativeCondSet);
557 isl_set_free(ConsequenceCondSet);
558 return false;
559 }
560
561 ConditionSets.push_back(ConsequenceCondSet);
562 ConditionSets.push_back(isl_set_coalesce(AlternativeCondSet));
563
564 return true;
565}
566
568 BasicBlock *BB, Instruction *TI, Loop *L, __isl_keep isl_set *Domain,
569 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
570 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
571 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
572 return buildConditionSets(BB, SI, L, Domain, InvalidDomainMap,
573 ConditionSets);
574
575 assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
576
577 if (TI->getNumSuccessors() == 1) {
578 ConditionSets.push_back(isl_set_copy(Domain));
579 return true;
580 }
581
582 Value *Condition = getConditionFromTerminator(TI);
583 assert(Condition && "No condition for Terminator");
584
585 return buildConditionSets(BB, Condition, TI, L, Domain, InvalidDomainMap,
586 ConditionSets);
587}
588
590 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
591 // Iterate over the region R and propagate the domain constrains from the
592 // predecessors to the current node. In contrast to the
593 // buildDomainsWithBranchConstraints function, this one will pull the domain
594 // information from the predecessors instead of pushing it to the successors.
595 // Additionally, we assume the domains to be already present in the domain
596 // map here. However, we iterate again in reverse post order so we know all
597 // predecessors have been visited before a block or non-affine subregion is
598 // visited.
599
600 ReversePostOrderTraversal<Region *> RTraversal(R);
601 for (auto *RN : RTraversal) {
602 // Recurse for affine subregions but go on for basic blocks and non-affine
603 // subregions.
604 if (RN->isSubRegion()) {
605 Region *SubRegion = RN->getNodeAs<Region>();
606 if (!scop->isNonAffineSubRegion(SubRegion)) {
607 if (!propagateDomainConstraints(SubRegion, InvalidDomainMap))
608 return false;
609 continue;
610 }
611 }
612
613 BasicBlock *BB = getRegionNodeBasicBlock(RN);
614 isl::set &Domain = scop->getOrInitEmptyDomain(BB);
615 assert(!Domain.is_null());
616
617 // Under the union of all predecessor conditions we can reach this block.
619 Domain = Domain.intersect(PredDom).coalesce();
620 Domain = Domain.align_params(scop->getParamSpace());
621
622 Loop *BBLoop = getRegionNodeLoop(RN, LI);
623 if (BBLoop && BBLoop->getHeader() == BB && scop->contains(BBLoop))
624 if (!addLoopBoundsToHeaderDomain(BBLoop, InvalidDomainMap))
625 return false;
626 }
627
628 return true;
629}
630
632 BasicBlock *BB, Loop *BBLoop,
633 SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks,
634 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
635 // Check if the block @p BB is the entry of a region. If so we propagate it's
636 // domain to the exit block of the region. Otherwise we are done.
637 auto *RI = scop->getRegion().getRegionInfo();
638 auto *BBReg = RI ? RI->getRegionFor(BB) : nullptr;
639 auto *ExitBB = BBReg ? BBReg->getExit() : nullptr;
640 if (!BBReg || BBReg->getEntry() != BB || !scop->contains(ExitBB))
641 return;
642
643 // Do not propagate the domain if there is a loop backedge inside the region
644 // that would prevent the exit block from being executed.
645 auto *L = BBLoop;
646 while (L && scop->contains(L)) {
647 SmallVector<BasicBlock *, 4> LatchBBs;
648 BBLoop->getLoopLatches(LatchBBs);
649 for (auto *LatchBB : LatchBBs)
650 if (BB != LatchBB && BBReg->contains(LatchBB))
651 return;
652 L = L->getParentLoop();
653 }
654
655 isl::set Domain = scop->getOrInitEmptyDomain(BB);
656 assert(!Domain.is_null() && "Cannot propagate a nullptr");
657
658 Loop *ExitBBLoop = getFirstNonBoxedLoopFor(ExitBB, LI, scop->getBoxedLoops());
659
660 // Since the dimensions of @p BB and @p ExitBB might be different we have to
661 // adjust the domain before we can propagate it.
662 isl::set AdjustedDomain = adjustDomainDimensions(Domain, BBLoop, ExitBBLoop);
663 isl::set &ExitDomain = scop->getOrInitEmptyDomain(ExitBB);
664
665 // If the exit domain is not yet created we set it otherwise we "add" the
666 // current domain.
667 ExitDomain =
668 !ExitDomain.is_null() ? AdjustedDomain.unite(ExitDomain) : AdjustedDomain;
669
670 // Initialize the invalid domain.
671 InvalidDomainMap[ExitBB] = ExitDomain.empty(ExitDomain.get_space());
672
673 FinishedExitBlocks.insert(ExitBB);
674}
675
678 // If @p BB is the ScopEntry we are done
679 if (scop->getRegion().getEntry() == BB)
680 return isl::set::universe(Domain.get_space());
681
682 // The region info of this function.
683 auto &RI = *scop->getRegion().getRegionInfo();
684
685 Loop *BBLoop = getFirstNonBoxedLoopFor(BB, LI, scop->getBoxedLoops());
686
687 // A domain to collect all predecessor domains, thus all conditions under
688 // which the block is executed. To this end we start with the empty domain.
689 isl::set PredDom = isl::set::empty(Domain.get_space());
690
691 // Set of regions of which the entry block domain has been propagated to BB.
692 // all predecessors inside any of the regions can be skipped.
693 SmallPtrSet<Region *, 8> PropagatedRegions;
694
695 for (auto *PredBB : predecessors(BB)) {
696 // Skip backedges.
697 if (DT.dominates(BB, PredBB))
698 continue;
699
700 // If the predecessor is in a region we used for propagation we can skip it.
701 auto PredBBInRegion = [PredBB](Region *PR) { return PR->contains(PredBB); };
702 if (llvm::any_of(PropagatedRegions, PredBBInRegion)) {
703 continue;
704 }
705
706 // Check if there is a valid region we can use for propagation, thus look
707 // for a region that contains the predecessor and has @p BB as exit block.
708 // FIXME: This was an side-effect-free (and possibly infinite) loop when
709 // committed and seems not to be needed.
710 auto *PredR = RI.getRegionFor(PredBB);
711 while (PredR->getExit() != BB && !PredR->contains(BB))
712 PredR = PredR->getParent();
713
714 // If a valid region for propagation was found use the entry of that region
715 // for propagation, otherwise the PredBB directly.
716 if (PredR->getExit() == BB) {
717 PredBB = PredR->getEntry();
718 PropagatedRegions.insert(PredR);
719 }
720
721 isl::set PredBBDom = scop->getDomainConditions(PredBB);
722 Loop *PredBBLoop =
723 getFirstNonBoxedLoopFor(PredBB, LI, scop->getBoxedLoops());
724 PredBBDom = adjustDomainDimensions(PredBBDom, PredBBLoop, BBLoop);
725 PredDom = PredDom.unite(PredBBDom);
726 }
727
728 return PredDom;
729}
730
732 Loop *L, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
733 int LoopDepth = scop->getRelativeLoopDepth(L);
734 assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
735
736 BasicBlock *HeaderBB = L->getHeader();
737 assert(scop->isDomainDefined(HeaderBB));
738 isl::set &HeaderBBDom = scop->getOrInitEmptyDomain(HeaderBB);
739
740 isl::map NextIterationMap =
741 createNextIterationMap(HeaderBBDom.get_space(), LoopDepth);
742
743 isl::set UnionBackedgeCondition = HeaderBBDom.empty(HeaderBBDom.get_space());
744
745 SmallVector<BasicBlock *, 4> LatchBlocks;
746 L->getLoopLatches(LatchBlocks);
747
748 for (BasicBlock *LatchBB : LatchBlocks) {
749 // If the latch is only reachable via error statements we skip it.
750 if (!scop->isDomainDefined(LatchBB))
751 continue;
752
753 isl::set LatchBBDom = scop->getDomainConditions(LatchBB);
754
755 isl::set BackedgeCondition;
756
757 Instruction *TI = LatchBB->getTerminator();
758 BranchInst *BI = dyn_cast<BranchInst>(TI);
759 assert(BI && "Only branch instructions allowed in loop latches");
760
761 if (BI->isUnconditional())
762 BackedgeCondition = LatchBBDom;
763 else {
764 SmallVector<isl_set *, 8> ConditionSets;
765 int idx = BI->getSuccessor(0) != HeaderBB;
766 if (!buildConditionSets(LatchBB, TI, L, LatchBBDom.get(),
767 InvalidDomainMap, ConditionSets))
768 return false;
769
770 // Free the non back edge condition set as we do not need it.
771 isl_set_free(ConditionSets[1 - idx]);
772
773 BackedgeCondition = isl::manage(ConditionSets[idx]);
774 }
775
776 int LatchLoopDepth = scop->getRelativeLoopDepth(LI.getLoopFor(LatchBB));
777 assert(LatchLoopDepth >= LoopDepth);
778 BackedgeCondition = BackedgeCondition.project_out(
779 isl::dim::set, LoopDepth + 1, LatchLoopDepth - LoopDepth);
780 UnionBackedgeCondition = UnionBackedgeCondition.unite(BackedgeCondition);
781 }
782
783 isl::map ForwardMap = ForwardMap.lex_le(HeaderBBDom.get_space());
784 for (int i = 0; i < LoopDepth; i++)
785 ForwardMap = ForwardMap.equate(isl::dim::in, i, isl::dim::out, i);
786
787 isl::set UnionBackedgeConditionComplement =
788 UnionBackedgeCondition.complement();
789 UnionBackedgeConditionComplement =
790 UnionBackedgeConditionComplement.lower_bound_si(isl::dim::set, LoopDepth,
791 0);
792 UnionBackedgeConditionComplement =
793 UnionBackedgeConditionComplement.apply(ForwardMap);
794 HeaderBBDom = HeaderBBDom.subtract(UnionBackedgeConditionComplement);
795 HeaderBBDom = HeaderBBDom.apply(NextIterationMap);
796
797 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
798 HeaderBBDom = Parts.second;
799
800 // Check if there is a <nsw> tagged AddRec for this loop and if so do not
801 // require a runtime check. The assumption is already implied by the <nsw>
802 // tag.
803 bool RequiresRTC = !scop->hasNSWAddRecForLoop(L);
804
805 isl::set UnboundedCtx = Parts.first.params();
807 HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION,
808 nullptr, RequiresRTC);
809 return true;
810}
811
813 DenseMap<std::pair<const SCEV *, Type *>, LoadInst *> EquivClasses;
814
815 const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
816 for (LoadInst *LInst : RIL) {
817 const SCEV *PointerSCEV = SE.getSCEV(LInst->getPointerOperand());
818
819 Type *Ty = LInst->getType();
820 LoadInst *&ClassRep = EquivClasses[std::make_pair(PointerSCEV, Ty)];
821 if (ClassRep) {
822 scop->addInvariantLoadMapping(LInst, ClassRep);
823 continue;
824 }
825
826 ClassRep = LInst;
827 scop->addInvariantEquivClass(
828 InvariantEquivClassTy{PointerSCEV, MemoryAccessList(), {}, Ty});
829 }
830}
831
833 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
834 bool IsOnlyNonAffineRegion = scop->isNonAffineSubRegion(R);
835 auto *EntryBB = R->getEntry();
836 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB);
837 int LD = scop->getRelativeLoopDepth(L);
838 auto *S =
839 isl_set_universe(isl_space_set_alloc(scop->getIslCtx().get(), 0, LD + 1));
840
841 InvalidDomainMap[EntryBB] = isl::manage(isl_set_empty(isl_set_get_space(S)));
843 scop->setDomain(EntryBB, Domain);
844
845 if (IsOnlyNonAffineRegion)
846 return !containsErrorBlock(R->getNode(), *R, &SD);
847
848 if (!buildDomainsWithBranchConstraints(R, InvalidDomainMap))
849 return false;
850
851 if (!propagateDomainConstraints(R, InvalidDomainMap))
852 return false;
853
854 // Error blocks and blocks dominated by them have been assumed to never be
855 // executed. Representing them in the Scop does not add any value. In fact,
856 // it is likely to cause issues during construction of the ScopStmts. The
857 // contents of error blocks have not been verified to be expressible and
858 // will cause problems when building up a ScopStmt for them.
859 // Furthermore, basic blocks dominated by error blocks may reference
860 // instructions in the error block which, if the error block is not modeled,
861 // can themselves not be constructed properly. To this end we will replace
862 // the domains of error blocks and those only reachable via error blocks
863 // with an empty set. Additionally, we will record for each block under which
864 // parameter combination it would be reached via an error block in its
865 // InvalidDomain. This information is needed during load hoisting.
866 if (!propagateInvalidStmtDomains(R, InvalidDomainMap))
867 return false;
868
869 return true;
870}
871
873 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
874 // To create the domain for each block in R we iterate over all blocks and
875 // subregions in R and propagate the conditions under which the current region
876 // element is executed. To this end we iterate in reverse post order over R as
877 // it ensures that we first visit all predecessors of a region node (either a
878 // basic block or a subregion) before we visit the region node itself.
879 // Initially, only the domain for the SCoP region entry block is set and from
880 // there we propagate the current domain to all successors, however we add the
881 // condition that the successor is actually executed next.
882 // As we are only interested in non-loop carried constraints here we can
883 // simply skip loop back edges.
884
885 SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks;
886 ReversePostOrderTraversal<Region *> RTraversal(R);
887 for (auto *RN : RTraversal) {
888 // Recurse for affine subregions but go on for basic blocks and non-affine
889 // subregions.
890 if (RN->isSubRegion()) {
891 Region *SubRegion = RN->getNodeAs<Region>();
892 if (!scop->isNonAffineSubRegion(SubRegion)) {
893 if (!buildDomainsWithBranchConstraints(SubRegion, InvalidDomainMap))
894 return false;
895 continue;
896 }
897 }
898
899 if (containsErrorBlock(RN, scop->getRegion(), &SD))
900 scop->notifyErrorBlock();
901 ;
902
903 BasicBlock *BB = getRegionNodeBasicBlock(RN);
904 Instruction *TI = BB->getTerminator();
905
906 if (isa<UnreachableInst>(TI))
907 continue;
908
909 if (!scop->isDomainDefined(BB))
910 continue;
911 isl::set Domain = scop->getDomainConditions(BB);
912
913 scop->updateMaxLoopDepth(unsignedFromIslSize(Domain.tuple_dim()));
914
915 auto *BBLoop = getRegionNodeLoop(RN, LI);
916 // Propagate the domain from BB directly to blocks that have a superset
917 // domain, at the moment only region exit nodes of regions that start in BB.
918 propagateDomainConstraintsToRegionExit(BB, BBLoop, FinishedExitBlocks,
919 InvalidDomainMap);
920
921 // If all successors of BB have been set a domain through the propagation
922 // above we do not need to build condition sets but can just skip this
923 // block. However, it is important to note that this is a local property
924 // with regards to the region @p R. To this end FinishedExitBlocks is a
925 // local variable.
926 auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) {
927 return FinishedExitBlocks.count(SuccBB);
928 };
929 if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit))
930 continue;
931
932 // Build the condition sets for the successor nodes of the current region
933 // node. If it is a non-affine subregion we will always execute the single
934 // exit node, hence the single entry node domain is the condition set. For
935 // basic blocks we use the helper function buildConditionSets.
936 SmallVector<isl_set *, 8> ConditionSets;
937 if (RN->isSubRegion())
938 ConditionSets.push_back(Domain.copy());
939 else if (!buildConditionSets(BB, TI, BBLoop, Domain.get(), InvalidDomainMap,
940 ConditionSets))
941 return false;
942
943 // Now iterate over the successors and set their initial domain based on
944 // their condition set. We skip back edges here and have to be careful when
945 // we leave a loop not to keep constraints over a dimension that doesn't
946 // exist anymore.
947 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
948 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
949 isl::set CondSet = isl::manage(ConditionSets[u]);
950 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
951
952 // Skip blocks outside the region.
953 if (!scop->contains(SuccBB))
954 continue;
955
956 // If we propagate the domain of some block to "SuccBB" we do not have to
957 // adjust the domain.
958 if (FinishedExitBlocks.count(SuccBB))
959 continue;
960
961 // Skip back edges.
962 if (DT.dominates(SuccBB, BB))
963 continue;
964
965 Loop *SuccBBLoop =
966 getFirstNonBoxedLoopFor(SuccBB, LI, scop->getBoxedLoops());
967
968 CondSet = adjustDomainDimensions(CondSet, BBLoop, SuccBBLoop);
969
970 // Set the domain for the successor or merge it with an existing domain in
971 // case there are multiple paths (without loop back edges) to the
972 // successor block.
973 isl::set &SuccDomain = scop->getOrInitEmptyDomain(SuccBB);
974
975 if (!SuccDomain.is_null()) {
976 SuccDomain = SuccDomain.unite(CondSet).coalesce();
977 } else {
978 // Initialize the invalid domain.
979 InvalidDomainMap[SuccBB] = CondSet.empty(CondSet.get_space());
980 SuccDomain = CondSet;
981 }
982
983 SuccDomain = SuccDomain.detect_equalities();
984
985 // Check if the maximal number of domain disjunctions was reached.
986 // In case this happens we will clean up and bail.
988 continue;
989
990 scop->invalidate(COMPLEXITY, DebugLoc());
991 while (++u < ConditionSets.size())
992 isl_set_free(ConditionSets[u]);
993 return false;
994 }
995 }
996
997 return true;
998}
999
1001 Region *R, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1002 ReversePostOrderTraversal<Region *> RTraversal(R);
1003 for (auto *RN : RTraversal) {
1004
1005 // Recurse for affine subregions but go on for basic blocks and non-affine
1006 // subregions.
1007 if (RN->isSubRegion()) {
1008 Region *SubRegion = RN->getNodeAs<Region>();
1009 if (!scop->isNonAffineSubRegion(SubRegion)) {
1010 propagateInvalidStmtDomains(SubRegion, InvalidDomainMap);
1011 continue;
1012 }
1013 }
1014
1015 bool ContainsErrorBlock = containsErrorBlock(RN, scop->getRegion(), &SD);
1016 BasicBlock *BB = getRegionNodeBasicBlock(RN);
1017 isl::set &Domain = scop->getOrInitEmptyDomain(BB);
1018 assert(!Domain.is_null() && "Cannot propagate a nullptr");
1019
1020 isl::set InvalidDomain = InvalidDomainMap[BB];
1021
1022 bool IsInvalidBlock = ContainsErrorBlock || Domain.is_subset(InvalidDomain);
1023
1024 if (!IsInvalidBlock) {
1025 InvalidDomain = InvalidDomain.intersect(Domain);
1026 } else {
1027 InvalidDomain = Domain;
1028 isl::set DomPar = Domain.params();
1030 BB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
1031 Domain = isl::set::empty(Domain.get_space());
1032 }
1033
1034 if (InvalidDomain.is_empty()) {
1035 InvalidDomainMap[BB] = InvalidDomain;
1036 continue;
1037 }
1038
1039 auto *BBLoop = getRegionNodeLoop(RN, LI);
1040 auto *TI = BB->getTerminator();
1041 unsigned NumSuccs = RN->isSubRegion() ? 1 : TI->getNumSuccessors();
1042 for (unsigned u = 0; u < NumSuccs; u++) {
1043 auto *SuccBB = getRegionNodeSuccessor(RN, TI, u);
1044
1045 // Skip successors outside the SCoP.
1046 if (!scop->contains(SuccBB))
1047 continue;
1048
1049 // Skip backedges.
1050 if (DT.dominates(SuccBB, BB))
1051 continue;
1052
1053 Loop *SuccBBLoop =
1054 getFirstNonBoxedLoopFor(SuccBB, LI, scop->getBoxedLoops());
1055
1056 auto AdjustedInvalidDomain =
1057 adjustDomainDimensions(InvalidDomain, BBLoop, SuccBBLoop);
1058
1059 isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB];
1060 SuccInvalidDomain = SuccInvalidDomain.unite(AdjustedInvalidDomain);
1061 SuccInvalidDomain = SuccInvalidDomain.coalesce();
1062
1063 InvalidDomainMap[SuccBB] = SuccInvalidDomain;
1064
1065 // Check if the maximal number of domain disjunctions was reached.
1066 // In case this happens we will bail.
1067 if (unsignedFromIslSize(SuccInvalidDomain.n_basic_set()) <
1069 continue;
1070
1071 InvalidDomainMap.erase(BB);
1072 scop->invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent());
1073 return false;
1074 }
1075
1076 InvalidDomainMap[BB] = InvalidDomain;
1077 }
1078
1079 return true;
1080}
1081
1083 Region *NonAffineSubRegion,
1084 bool IsExitBlock) {
1085 // PHI nodes that are in the exit block of the region, hence if IsExitBlock is
1086 // true, are not modeled as ordinary PHI nodes as they are not part of the
1087 // region. However, we model the operands in the predecessor blocks that are
1088 // part of the region as regular scalar accesses.
1089
1090 // If we can synthesize a PHI we can skip it, however only if it is in
1091 // the region. If it is not it can only be in the exit block of the region.
1092 // In this case we model the operands but not the PHI itself.
1093 auto *Scope = LI.getLoopFor(PHI->getParent());
1094 if (!IsExitBlock && canSynthesize(PHI, *scop, &SE, Scope))
1095 return;
1096
1097 // PHI nodes are modeled as if they had been demoted prior to the SCoP
1098 // detection. Hence, the PHI is a load of a new memory location in which the
1099 // incoming value was written at the end of the incoming basic block.
1100 bool OnlyNonAffineSubRegionOperands = true;
1101 for (unsigned u = 0; u < PHI->getNumIncomingValues(); u++) {
1102 Value *Op = PHI->getIncomingValue(u);
1103 BasicBlock *OpBB = PHI->getIncomingBlock(u);
1104 ScopStmt *OpStmt = scop->getIncomingStmtFor(PHI->getOperandUse(u));
1105
1106 // Do not build PHI dependences inside a non-affine subregion, but make
1107 // sure that the necessary scalar values are still made available.
1108 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB)) {
1109 auto *OpInst = dyn_cast<Instruction>(Op);
1110 if (!OpInst || !NonAffineSubRegion->contains(OpInst))
1111 ensureValueRead(Op, OpStmt);
1112 continue;
1113 }
1114
1115 OnlyNonAffineSubRegionOperands = false;
1116 ensurePHIWrite(PHI, OpStmt, OpBB, Op, IsExitBlock);
1117 }
1118
1119 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) {
1120 addPHIReadAccess(PHIStmt, PHI);
1121 }
1122}
1123
1125 Instruction *Inst) {
1126 assert(!isa<PHINode>(Inst));
1127
1128 // Pull-in required operands.
1129 for (Use &Op : Inst->operands())
1130 ensureValueRead(Op.get(), UserStmt);
1131}
1132
1133// Create a sequence of two schedules. Either argument may be null and is
1134// interpreted as the empty schedule. Can also return null if both schedules are
1135// empty.
1137 if (Prev.is_null())
1138 return Succ;
1139 if (Succ.is_null())
1140 return Prev;
1141
1142 return Prev.sequence(Succ);
1143}
1144
1145// Create an isl_multi_union_aff that defines an identity mapping from the
1146// elements of USet to their N-th dimension.
1147//
1148// # Example:
1149//
1150// Domain: { A[i,j]; B[i,j,k] }
1151// N: 1
1152//
1153// Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] }
1154//
1155// @param USet A union set describing the elements for which to generate a
1156// mapping.
1157// @param N The dimension to map to.
1158// @returns A mapping from USet to its N-th dimension.
1160 assert(!USet.is_null());
1161 assert(!USet.is_empty());
1162
1163 auto Result = isl::union_pw_multi_aff::empty(USet.get_space());
1164
1165 for (isl::set S : USet.get_set_list()) {
1166 unsigned Dim = unsignedFromIslSize(S.tuple_dim());
1167 assert(Dim >= N);
1168 auto PMA = isl::pw_multi_aff::project_out_map(S.get_space(), isl::dim::set,
1169 N, Dim - N);
1170 if (N > 1)
1171 PMA = PMA.drop_dims(isl::dim::out, 0, N - 1);
1172
1173 Result = Result.add_pw_multi_aff(PMA);
1174 }
1175
1177}
1178
1180 Loop *L = getLoopSurroundingScop(*scop, LI);
1181 LoopStackTy LoopStack({LoopStackElementTy(L, {}, 0)});
1182 buildSchedule(scop->getRegion().getNode(), LoopStack);
1183 assert(LoopStack.size() == 1 && LoopStack.back().L == L);
1184 scop->setScheduleTree(LoopStack[0].Schedule);
1185}
1186
1187/// To generate a schedule for the elements in a Region we traverse the Region
1188/// in reverse-post-order and add the contained RegionNodes in traversal order
1189/// to the schedule of the loop that is currently at the top of the LoopStack.
1190/// For loop-free codes, this results in a correct sequential ordering.
1191///
1192/// Example:
1193/// bb1(0)
1194/// / \.
1195/// bb2(1) bb3(2)
1196/// \ / \.
1197/// bb4(3) bb5(4)
1198/// \ /
1199/// bb6(5)
1200///
1201/// Including loops requires additional processing. Whenever a loop header is
1202/// encountered, the corresponding loop is added to the @p LoopStack. Starting
1203/// from an empty schedule, we first process all RegionNodes that are within
1204/// this loop and complete the sequential schedule at this loop-level before
1205/// processing about any other nodes. To implement this
1206/// loop-nodes-first-processing, the reverse post-order traversal is
1207/// insufficient. Hence, we additionally check if the traversal yields
1208/// sub-regions or blocks that are outside the last loop on the @p LoopStack.
1209/// These region-nodes are then queue and only traverse after the all nodes
1210/// within the current loop have been processed.
1211void ScopBuilder::buildSchedule(Region *R, LoopStackTy &LoopStack) {
1212 Loop *OuterScopLoop = getLoopSurroundingScop(*scop, LI);
1213
1214 ReversePostOrderTraversal<Region *> RTraversal(R);
1215 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end());
1216 std::deque<RegionNode *> DelayList;
1217 bool LastRNWaiting = false;
1218
1219 // Iterate over the region @p R in reverse post-order but queue
1220 // sub-regions/blocks iff they are not part of the last encountered but not
1221 // completely traversed loop. The variable LastRNWaiting is a flag to indicate
1222 // that we queued the last sub-region/block from the reverse post-order
1223 // iterator. If it is set we have to explore the next sub-region/block from
1224 // the iterator (if any) to guarantee progress. If it is not set we first try
1225 // the next queued sub-region/blocks.
1226 while (!WorkList.empty() || !DelayList.empty()) {
1227 RegionNode *RN;
1228
1229 if ((LastRNWaiting && !WorkList.empty()) || DelayList.empty()) {
1230 RN = WorkList.front();
1231 WorkList.pop_front();
1232 LastRNWaiting = false;
1233 } else {
1234 RN = DelayList.front();
1235 DelayList.pop_front();
1236 }
1237
1238 Loop *L = getRegionNodeLoop(RN, LI);
1239 if (!scop->contains(L))
1240 L = OuterScopLoop;
1241
1242 Loop *LastLoop = LoopStack.back().L;
1243 if (LastLoop != L) {
1244 if (LastLoop && !LastLoop->contains(L)) {
1245 LastRNWaiting = true;
1246 DelayList.push_back(RN);
1247 continue;
1248 }
1249 LoopStack.push_back({L, {}, 0});
1250 }
1251 buildSchedule(RN, LoopStack);
1252 }
1253}
1254
1255void ScopBuilder::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack) {
1256 if (RN->isSubRegion()) {
1257 auto *LocalRegion = RN->getNodeAs<Region>();
1258 if (!scop->isNonAffineSubRegion(LocalRegion)) {
1259 buildSchedule(LocalRegion, LoopStack);
1260 return;
1261 }
1262 }
1263
1264 assert(LoopStack.rbegin() != LoopStack.rend());
1265 auto LoopData = LoopStack.rbegin();
1266 LoopData->NumBlocksProcessed += getNumBlocksInRegionNode(RN);
1267
1268 for (auto *Stmt : scop->getStmtListFor(RN)) {
1269 isl::union_set UDomain{Stmt->getDomain()};
1270 auto StmtSchedule = isl::schedule::from_domain(UDomain);
1271 LoopData->Schedule = combineInSequence(LoopData->Schedule, StmtSchedule);
1272 }
1273
1274 // Check if we just processed the last node in this loop. If we did, finalize
1275 // the loop by:
1276 //
1277 // - adding new schedule dimensions
1278 // - folding the resulting schedule into the parent loop schedule
1279 // - dropping the loop schedule from the LoopStack.
1280 //
1281 // Then continue to check surrounding loops, which might also have been
1282 // completed by this node.
1283 size_t Dimension = LoopStack.size();
1284 while (LoopData->L &&
1285 LoopData->NumBlocksProcessed == getNumBlocksInLoop(LoopData->L)) {
1286 isl::schedule Schedule = LoopData->Schedule;
1287 auto NumBlocksProcessed = LoopData->NumBlocksProcessed;
1288
1289 assert(std::next(LoopData) != LoopStack.rend());
1290 Loop *L = LoopData->L;
1291 ++LoopData;
1292 --Dimension;
1293
1294 if (!Schedule.is_null()) {
1295 isl::union_set Domain = Schedule.get_domain();
1297 Schedule = Schedule.insert_partial_schedule(MUPA);
1298
1300 /// If any of the loops has a disable_nonforced heuristic, mark the
1301 /// entire SCoP as such. The ISL rescheduler can only reschedule the
1302 /// SCoP in its entirety.
1303 /// TODO: ScopDetection could avoid including such loops or warp them as
1304 /// boxed loop. It still needs to pass-through loop with user-defined
1305 /// metadata.
1306 scop->markDisableHeuristics();
1307 }
1308
1309 // It is easier to insert the marks here that do it retroactively.
1310 isl::id IslLoopId = createIslLoopAttr(scop->getIslCtx(), L);
1311 if (!IslLoopId.is_null())
1312 Schedule =
1313 Schedule.get_root().child(0).insert_mark(IslLoopId).get_schedule();
1314
1315 LoopData->Schedule = combineInSequence(LoopData->Schedule, Schedule);
1316 }
1317
1318 LoopData->NumBlocksProcessed += NumBlocksProcessed;
1319 }
1320 // Now pop all loops processed up there from the LoopStack
1321 LoopStack.erase(LoopStack.begin() + Dimension, LoopStack.end());
1322}
1323
1325 // Check for uses of this instruction outside the scop. Because we do not
1326 // iterate over such instructions and therefore did not "ensure" the existence
1327 // of a write, we must determine such use here.
1328 if (scop->isEscaping(Inst))
1329 ensureValueWrite(Inst);
1330}
1331
1333 for (auto &AS : llvm::reverse(RecordedAssumptions)) {
1334
1335 if (!AS.BB) {
1336 scop->addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign,
1337 nullptr /* BasicBlock */, AS.RequiresRTC);
1338 continue;
1339 }
1340
1341 // If the domain was deleted the assumptions are void.
1342 isl_set *Dom = scop->getDomainConditions(AS.BB).release();
1343 if (!Dom)
1344 continue;
1345
1346 // If a basic block was given use its domain to simplify the assumption.
1347 // In case of restrictions we know they only have to hold on the domain,
1348 // thus we can intersect them with the domain of the block. However, for
1349 // assumptions the domain has to imply them, thus:
1350 // _ _____
1351 // Dom => S <==> A v B <==> A - B
1352 //
1353 // To avoid the complement we will register A - B as a restriction not an
1354 // assumption.
1355 isl_set *S = AS.Set.copy();
1356 if (AS.Sign == AS_RESTRICTION)
1358 else /* (AS.Sign == AS_ASSUMPTION) */
1360
1361 scop->addAssumption(AS.Kind, isl::manage(S), AS.Loc, AS_RESTRICTION, AS.BB,
1362 AS.RequiresRTC);
1363 }
1364}
1365
1367 AssumptionCache &AC, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
1368 for (auto &Assumption : AC.assumptions()) {
1369 auto *CI = dyn_cast_or_null<CallInst>(Assumption);
1370 if (!CI || CI->arg_size() != 1)
1371 continue;
1372
1373 bool InScop = scop->contains(CI);
1374 if (!InScop && !scop->isDominatedBy(DT, CI->getParent()))
1375 continue;
1376
1377 auto *L = LI.getLoopFor(CI->getParent());
1378 auto *Val = CI->getArgOperand(0);
1379 ParameterSetTy DetectedParams;
1380 auto &R = scop->getRegion();
1381 if (!isAffineConstraint(Val, &R, L, SE, DetectedParams)) {
1382 ORE.emit(
1383 OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI)
1384 << "Non-affine user assumption ignored.");
1385 continue;
1386 }
1387
1388 // Collect all newly introduced parameters.
1389 ParameterSetTy NewParams;
1390 for (auto *Param : DetectedParams) {
1391 Param = extractConstantFactor(Param, SE).second;
1392 Param = scop->getRepresentingInvariantLoadSCEV(Param);
1393 if (scop->isParam(Param))
1394 continue;
1395 NewParams.insert(Param);
1396 }
1397
1398 SmallVector<isl_set *, 2> ConditionSets;
1399 auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr;
1400 BasicBlock *BB = InScop ? CI->getParent() : R.getEntry();
1401 auto *Dom = InScop ? isl_set_copy(scop->getDomainConditions(BB).get())
1402 : isl_set_copy(scop->getContext().get());
1403 assert(Dom && "Cannot propagate a nullptr.");
1404 bool Valid = buildConditionSets(BB, Val, TI, L, Dom, InvalidDomainMap,
1405 ConditionSets);
1406 isl_set_free(Dom);
1407
1408 if (!Valid)
1409 continue;
1410
1411 isl_set *AssumptionCtx = nullptr;
1412 if (InScop) {
1413 AssumptionCtx = isl_set_complement(isl_set_params(ConditionSets[1]));
1414 isl_set_free(ConditionSets[0]);
1415 } else {
1416 AssumptionCtx = isl_set_complement(ConditionSets[1]);
1417 AssumptionCtx = isl_set_intersect(AssumptionCtx, ConditionSets[0]);
1418 }
1419
1420 // Project out newly introduced parameters as they are not otherwise useful.
1421 if (!NewParams.empty()) {
1422 for (isl_size u = 0; u < isl_set_n_param(AssumptionCtx); u++) {
1423 auto *Id = isl_set_get_dim_id(AssumptionCtx, isl_dim_param, u);
1424 auto *Param = static_cast<const SCEV *>(isl_id_get_user(Id));
1425 isl_id_free(Id);
1426
1427 if (!NewParams.count(Param))
1428 continue;
1429
1430 AssumptionCtx =
1431 isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1);
1432 }
1433 }
1434 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI)
1435 << "Use user assumption: "
1436 << stringFromIslObj(AssumptionCtx, "null"));
1437 isl::set newContext =
1438 scop->getContext().intersect(isl::manage(AssumptionCtx));
1439 scop->setContext(newContext);
1440 }
1441}
1442
1444 // Memory builtins are not considered in this function.
1445 if (!Inst.isLoad() && !Inst.isStore())
1446 return false;
1447
1448 Value *Val = Inst.getValueOperand();
1449 Type *ElementType = Val->getType();
1450 Value *Address = Inst.getPointerOperand();
1451 const SCEV *AccessFunction =
1452 SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
1453 const SCEVUnknown *BasePointer =
1454 dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
1455 enum MemoryAccess::AccessType AccType =
1456 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
1457
1458 if (auto *BitCast = dyn_cast<BitCastInst>(Address))
1459 Address = BitCast->getOperand(0);
1460
1461 auto *GEP = dyn_cast<GetElementPtrInst>(Address);
1462 if (!GEP || DL.getTypeAllocSize(GEP->getResultElementType()) !=
1463 DL.getTypeAllocSize(ElementType))
1464 return false;
1465
1466 SmallVector<const SCEV *, 4> Subscripts;
1467 SmallVector<int, 4> Sizes;
1468 getIndexExpressionsFromGEP(SE, GEP, Subscripts, Sizes);
1469 auto *BasePtr = GEP->getOperand(0);
1470
1471 if (auto *BasePtrCast = dyn_cast<BitCastInst>(BasePtr))
1472 BasePtr = BasePtrCast->getOperand(0);
1473
1474 // Check for identical base pointers to ensure that we do not miss index
1475 // offsets that have been added before this GEP is applied.
1476 if (BasePtr != BasePointer->getValue())
1477 return false;
1478
1479 std::vector<const SCEV *> SizesSCEV;
1480
1481 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1482
1483 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1484 for (auto *Subscript : Subscripts) {
1485 InvariantLoadsSetTy AccessILS;
1486 if (!isAffineExpr(&scop->getRegion(), SurroundingLoop, Subscript, SE,
1487 &AccessILS))
1488 return false;
1489
1490 for (LoadInst *LInst : AccessILS)
1491 if (!ScopRIL.count(LInst))
1492 return false;
1493 }
1494
1495 if (Sizes.empty())
1496 return false;
1497
1498 SizesSCEV.push_back(nullptr);
1499
1500 for (auto V : Sizes)
1501 SizesSCEV.push_back(SE.getSCEV(
1502 ConstantInt::get(IntegerType::getInt64Ty(BasePtr->getContext()), V)));
1503
1504 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1505 true, Subscripts, SizesSCEV, Val);
1506 return true;
1507}
1508
1510 // Memory builtins are not considered by this function.
1511 if (!Inst.isLoad() && !Inst.isStore())
1512 return false;
1513
1514 if (!PollyDelinearize)
1515 return false;
1516
1517 Value *Address = Inst.getPointerOperand();
1518 Value *Val = Inst.getValueOperand();
1519 Type *ElementType = Val->getType();
1520 unsigned ElementSize = DL.getTypeAllocSize(ElementType);
1521 enum MemoryAccess::AccessType AccType =
1522 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
1523
1524 const SCEV *AccessFunction =
1525 SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
1526 const SCEVUnknown *BasePointer =
1527 dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
1528
1529 assert(BasePointer && "Could not find base pointer");
1530
1531 auto &InsnToMemAcc = scop->getInsnToMemAccMap();
1532 auto AccItr = InsnToMemAcc.find(Inst);
1533 if (AccItr == InsnToMemAcc.end())
1534 return false;
1535
1536 std::vector<const SCEV *> Sizes = {nullptr};
1537
1538 Sizes.insert(Sizes.end(), AccItr->second.Shape->DelinearizedSizes.begin(),
1539 AccItr->second.Shape->DelinearizedSizes.end());
1540
1541 // In case only the element size is contained in the 'Sizes' array, the
1542 // access does not access a real multi-dimensional array. Hence, we allow
1543 // the normal single-dimensional access construction to handle this.
1544 if (Sizes.size() == 1)
1545 return false;
1546
1547 // Remove the element size. This information is already provided by the
1548 // ElementSize parameter. In case the element size of this access and the
1549 // element size used for delinearization differs the delinearization is
1550 // incorrect. Hence, we invalidate the scop.
1551 //
1552 // TODO: Handle delinearization with differing element sizes.
1553 auto DelinearizedSize =
1554 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
1555 Sizes.pop_back();
1556 if (ElementSize != DelinearizedSize)
1557 scop->invalidate(DELINEARIZATION, Inst->getDebugLoc(), Inst->getParent());
1558
1559 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1560 true, AccItr->second.DelinearizedSubscripts, Sizes, Val);
1561 return true;
1562}
1563
1565 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst);
1566
1567 if (MemIntr == nullptr)
1568 return false;
1569
1570 auto *L = LI.getLoopFor(Inst->getParent());
1571 const SCEV *LengthVal = SE.getSCEVAtScope(MemIntr->getLength(), L);
1572 assert(LengthVal);
1573
1574 // Check if the length val is actually affine or if we overapproximate it
1575 InvariantLoadsSetTy AccessILS;
1576 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1577
1578 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1579 bool LengthIsAffine = isAffineExpr(&scop->getRegion(), SurroundingLoop,
1580 LengthVal, SE, &AccessILS);
1581 for (LoadInst *LInst : AccessILS)
1582 if (!ScopRIL.count(LInst))
1583 LengthIsAffine = false;
1584 if (!LengthIsAffine)
1585 LengthVal = nullptr;
1586
1587 auto *DestPtrVal = MemIntr->getDest();
1588 assert(DestPtrVal);
1589
1590 const SCEV *DestAccFunc = SE.getSCEVAtScope(DestPtrVal, L);
1591 assert(DestAccFunc);
1592 // Ignore accesses to "NULL".
1593 // TODO: We could use this to optimize the region further, e.g., intersect
1594 // the context with
1595 // isl_set_complement(isl_set_params(getDomain()))
1596 // as we know it would be undefined to execute this instruction anyway.
1597 if (DestAccFunc->isZero())
1598 return true;
1599
1600 if (auto *U = dyn_cast<SCEVUnknown>(DestAccFunc)) {
1601 if (isa<ConstantPointerNull>(U->getValue()))
1602 return true;
1603 }
1604
1605 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE.getPointerBase(DestAccFunc));
1606 assert(DestPtrSCEV);
1607 DestAccFunc = SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
1608 addArrayAccess(Stmt, Inst, MemoryAccess::MUST_WRITE, DestPtrSCEV->getValue(),
1609 IntegerType::getInt8Ty(DestPtrVal->getContext()),
1610 LengthIsAffine, {DestAccFunc, LengthVal}, {nullptr},
1611 Inst.getValueOperand());
1612
1613 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr);
1614 if (!MemTrans)
1615 return true;
1616
1617 auto *SrcPtrVal = MemTrans->getSource();
1618 assert(SrcPtrVal);
1619
1620 const SCEV *SrcAccFunc = SE.getSCEVAtScope(SrcPtrVal, L);
1621 assert(SrcAccFunc);
1622 // Ignore accesses to "NULL".
1623 // TODO: See above TODO
1624 if (SrcAccFunc->isZero())
1625 return true;
1626
1627 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(SE.getPointerBase(SrcAccFunc));
1628 assert(SrcPtrSCEV);
1629 SrcAccFunc = SE.getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
1630 addArrayAccess(Stmt, Inst, MemoryAccess::READ, SrcPtrSCEV->getValue(),
1631 IntegerType::getInt8Ty(SrcPtrVal->getContext()),
1632 LengthIsAffine, {SrcAccFunc, LengthVal}, {nullptr},
1633 Inst.getValueOperand());
1634
1635 return true;
1636}
1637
1639 auto *CI = dyn_cast_or_null<CallInst>(Inst);
1640
1641 if (CI == nullptr)
1642 return false;
1643
1644 if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI) || isDebugCall(CI))
1645 return true;
1646
1647 const SCEV *AF = SE.getConstant(IntegerType::getInt64Ty(CI->getContext()), 0);
1648 auto *CalledFunction = CI->getCalledFunction();
1649 MemoryEffects ME = AA.getMemoryEffects(CalledFunction);
1650 if (ME.doesNotAccessMemory())
1651 return true;
1652
1653 if (ME.onlyAccessesArgPointees()) {
1654 ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
1655 auto AccType =
1656 !isModSet(ArgMR) ? MemoryAccess::READ : MemoryAccess::MAY_WRITE;
1657 Loop *L = LI.getLoopFor(Inst->getParent());
1658 for (const auto &Arg : CI->args()) {
1659 if (!Arg->getType()->isPointerTy())
1660 continue;
1661
1662 const SCEV *ArgSCEV = SE.getSCEVAtScope(Arg, L);
1663 if (ArgSCEV->isZero())
1664 continue;
1665
1666 if (auto *U = dyn_cast<SCEVUnknown>(ArgSCEV)) {
1667 if (isa<ConstantPointerNull>(U->getValue()))
1668 return true;
1669 }
1670
1671 auto *ArgBasePtr = cast<SCEVUnknown>(SE.getPointerBase(ArgSCEV));
1672 addArrayAccess(Stmt, Inst, AccType, ArgBasePtr->getValue(),
1673 ArgBasePtr->getType(), false, {AF}, {nullptr}, CI);
1674 }
1675 return true;
1676 }
1677
1678 if (ME.onlyReadsMemory()) {
1679 GlobalReads.emplace_back(Stmt, CI);
1680 return true;
1681 }
1682 return false;
1683}
1684
1686 // Memory builtins are not considered by this function.
1687 if (!Inst.isLoad() && !Inst.isStore())
1688 return false;
1689
1690 Value *Address = Inst.getPointerOperand();
1691 Value *Val = Inst.getValueOperand();
1692 Type *ElementType = Val->getType();
1693 enum MemoryAccess::AccessType AccType =
1694 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
1695
1696 const SCEV *AccessFunction =
1697 SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
1698 const SCEVUnknown *BasePointer =
1699 dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
1700
1701 assert(BasePointer && "Could not find base pointer");
1702 AccessFunction = SE.getMinusSCEV(AccessFunction, BasePointer);
1703
1704 // Check if the access depends on a loop contained in a non-affine subregion.
1705 bool isVariantInNonAffineLoop = false;
1706 SetVector<const Loop *> Loops;
1707 findLoops(AccessFunction, Loops);
1708 for (const Loop *L : Loops)
1709 if (Stmt->contains(L)) {
1710 isVariantInNonAffineLoop = true;
1711 break;
1712 }
1713
1714 InvariantLoadsSetTy AccessILS;
1715
1716 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1717 bool IsAffine = !isVariantInNonAffineLoop &&
1718 isAffineExpr(&scop->getRegion(), SurroundingLoop,
1719 AccessFunction, SE, &AccessILS);
1720
1721 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1722 for (LoadInst *LInst : AccessILS)
1723 if (!ScopRIL.count(LInst))
1724 IsAffine = false;
1725
1726 if (!IsAffine && AccType == MemoryAccess::MUST_WRITE)
1727 AccType = MemoryAccess::MAY_WRITE;
1728
1729 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1730 IsAffine, {AccessFunction}, {nullptr}, Val);
1731 return true;
1732}
1733
1735 if (buildAccessMemIntrinsic(Inst, Stmt))
1736 return;
1737
1738 if (buildAccessCallInst(Inst, Stmt))
1739 return;
1740
1741 if (buildAccessMultiDimFixed(Inst, Stmt))
1742 return;
1743
1744 if (buildAccessMultiDimParam(Inst, Stmt))
1745 return;
1746
1747 if (buildAccessSingleDim(Inst, Stmt))
1748 return;
1749
1750 llvm_unreachable(
1751 "At least one of the buildAccess functions must handled this access, or "
1752 "ScopDetection should have rejected this SCoP");
1753}
1754
1756 for (auto &Stmt : *scop) {
1757 if (Stmt.isBlockStmt()) {
1758 buildAccessFunctions(&Stmt, *Stmt.getBasicBlock());
1759 continue;
1760 }
1761
1762 Region *R = Stmt.getRegion();
1763 for (BasicBlock *BB : R->blocks())
1764 buildAccessFunctions(&Stmt, *BB, R);
1765 }
1766
1767 // Build write accesses for values that are used after the SCoP.
1768 // The instructions defining them might be synthesizable and therefore not
1769 // contained in any statement, hence we iterate over the original instructions
1770 // to identify all escaping values.
1771 for (BasicBlock *BB : scop->getRegion().blocks()) {
1772 for (Instruction &Inst : *BB)
1774 }
1775}
1776
1777bool ScopBuilder::shouldModelInst(Instruction *Inst, Loop *L) {
1778 return !Inst->isTerminator() && !isIgnoredIntrinsic(Inst) &&
1779 !canSynthesize(Inst, *scop, &SE, L);
1780}
1781
1782/// Generate a name for a statement.
1783///
1784/// @param BB The basic block the statement will represent.
1785/// @param BBIdx The index of the @p BB relative to other BBs/regions.
1786/// @param Count The index of the created statement in @p BB.
1787/// @param IsMain Whether this is the main of all statement for @p BB. If true,
1788/// no suffix will be added.
1789/// @param IsLast Uses a special indicator for the last statement of a BB.
1790static std::string makeStmtName(BasicBlock *BB, long BBIdx, int Count,
1791 bool IsMain, bool IsLast = false) {
1792 std::string Suffix;
1793 if (!IsMain) {
1795 Suffix = '_';
1796 if (IsLast)
1797 Suffix += "last";
1798 else if (Count < 26)
1799 Suffix += 'a' + Count;
1800 else
1801 Suffix += std::to_string(Count);
1802 }
1803 return getIslCompatibleName("Stmt", BB, BBIdx, Suffix, UseInstructionNames);
1804}
1805
1806/// Generate a name for a statement that represents a non-affine subregion.
1807///
1808/// @param R The region the statement will represent.
1809/// @param RIdx The index of the @p R relative to other BBs/regions.
1810static std::string makeStmtName(Region *R, long RIdx) {
1811 return getIslCompatibleName("Stmt", R->getNameStr(), RIdx, "",
1813}
1814
1815void ScopBuilder::buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore) {
1816 Loop *SurroundingLoop = LI.getLoopFor(BB);
1817
1818 int Count = 0;
1819 long BBIdx = scop->getNextStmtIdx();
1820 std::vector<Instruction *> Instructions;
1821 for (Instruction &Inst : *BB) {
1822 if (shouldModelInst(&Inst, SurroundingLoop))
1823 Instructions.push_back(&Inst);
1824 if (Inst.getMetadata("polly_split_after") ||
1825 (SplitOnStore && isa<StoreInst>(Inst))) {
1826 std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0);
1827 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1828 Count++;
1829 Instructions.clear();
1830 }
1831 }
1832
1833 std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0);
1834 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1835}
1836
1837/// Is @p Inst an ordered instruction?
1838///
1839/// An unordered instruction is an instruction, such that a sequence of
1840/// unordered instructions can be permuted without changing semantics. Any
1841/// instruction for which this is not always the case is ordered.
1842static bool isOrderedInstruction(Instruction *Inst) {
1843 return Inst->mayHaveSideEffects() || Inst->mayReadOrWriteMemory();
1844}
1845
1846/// Join instructions to the same statement if one uses the scalar result of the
1847/// other.
1848static void joinOperandTree(EquivalenceClasses<Instruction *> &UnionFind,
1849 ArrayRef<Instruction *> ModeledInsts) {
1850 for (Instruction *Inst : ModeledInsts) {
1851 if (isa<PHINode>(Inst))
1852 continue;
1853
1854 for (Use &Op : Inst->operands()) {
1855 Instruction *OpInst = dyn_cast<Instruction>(Op.get());
1856 if (!OpInst)
1857 continue;
1858
1859 // Check if OpInst is in the BB and is a modeled instruction.
1860 if (!UnionFind.contains(OpInst))
1861 continue;
1862
1863 UnionFind.unionSets(Inst, OpInst);
1864 }
1865 }
1866}
1867
1868/// Ensure that the order of ordered instructions does not change.
1869///
1870/// If we encounter an ordered instruction enclosed in instructions belonging to
1871/// a different statement (which might as well contain ordered instructions, but
1872/// this is not tested here), join them.
1873static void
1874joinOrderedInstructions(EquivalenceClasses<Instruction *> &UnionFind,
1875 ArrayRef<Instruction *> ModeledInsts) {
1876 SetVector<Instruction *> SeenLeaders;
1877 for (Instruction *Inst : ModeledInsts) {
1878 if (!isOrderedInstruction(Inst))
1879 continue;
1880
1881 Instruction *Leader = UnionFind.getLeaderValue(Inst);
1882 // Since previous iterations might have merged sets, some items in
1883 // SeenLeaders are not leaders anymore. However, The new leader of
1884 // previously merged instructions must be one of the former leaders of
1885 // these merged instructions.
1886 bool Inserted = SeenLeaders.insert(Leader);
1887 if (Inserted)
1888 continue;
1889
1890 // Merge statements to close holes. Say, we have already seen statements A
1891 // and B, in this order. Then we see an instruction of A again and we would
1892 // see the pattern "A B A". This function joins all statements until the
1893 // only seen occurrence of A.
1894 for (Instruction *Prev : reverse(SeenLeaders)) {
1895 // We are backtracking from the last element until we see Inst's leader
1896 // in SeenLeaders and merge all into one set. Although leaders of
1897 // instructions change during the execution of this loop, it's irrelevant
1898 // as we are just searching for the element that we already confirmed is
1899 // in the list.
1900 if (Prev == Leader)
1901 break;
1902 UnionFind.unionSets(Prev, Leader);
1903 }
1904 }
1905}
1906
1907/// If the BasicBlock has an edge from itself, ensure that the PHI WRITEs for
1908/// the incoming values from this block are executed after the PHI READ.
1909///
1910/// Otherwise it could overwrite the incoming value from before the BB with the
1911/// value for the next execution. This can happen if the PHI WRITE is added to
1912/// the statement with the instruction that defines the incoming value (instead
1913/// of the last statement of the same BB). To ensure that the PHI READ and WRITE
1914/// are in order, we put both into the statement. PHI WRITEs are always executed
1915/// after PHI READs when they are in the same statement.
1916///
1917/// TODO: This is an overpessimization. We only have to ensure that the PHI
1918/// WRITE is not put into a statement containing the PHI itself. That could also
1919/// be done by
1920/// - having all (strongly connected) PHIs in a single statement,
1921/// - unite only the PHIs in the operand tree of the PHI WRITE (because it only
1922/// has a chance of being lifted before a PHI by being in a statement with a
1923/// PHI that comes before in the basic block), or
1924/// - when uniting statements, ensure that no (relevant) PHIs are overtaken.
1925static void joinOrderedPHIs(EquivalenceClasses<Instruction *> &UnionFind,
1926 ArrayRef<Instruction *> ModeledInsts) {
1927 for (Instruction *Inst : ModeledInsts) {
1928 PHINode *PHI = dyn_cast<PHINode>(Inst);
1929 if (!PHI)
1930 continue;
1931
1932 int Idx = PHI->getBasicBlockIndex(PHI->getParent());
1933 if (Idx < 0)
1934 continue;
1935
1936 Instruction *IncomingVal =
1937 dyn_cast<Instruction>(PHI->getIncomingValue(Idx));
1938 if (!IncomingVal)
1939 continue;
1940
1941 UnionFind.unionSets(PHI, IncomingVal);
1942 }
1943}
1944
1946 Loop *L = LI.getLoopFor(BB);
1947
1948 // Extracting out modeled instructions saves us from checking
1949 // shouldModelInst() repeatedly.
1950 SmallVector<Instruction *, 32> ModeledInsts;
1951 EquivalenceClasses<Instruction *> UnionFind;
1952 Instruction *MainInst = nullptr, *MainLeader = nullptr;
1953 for (Instruction &Inst : *BB) {
1954 if (!shouldModelInst(&Inst, L))
1955 continue;
1956 ModeledInsts.push_back(&Inst);
1957 UnionFind.insert(&Inst);
1958
1959 // When a BB is split into multiple statements, the main statement is the
1960 // one containing the 'main' instruction. We select the first instruction
1961 // that is unlikely to be removed (because it has side-effects) as the main
1962 // one. It is used to ensure that at least one statement from the bb has the
1963 // same name as with -polly-stmt-granularity=bb.
1964 if (!MainInst && (isa<StoreInst>(Inst) ||
1965 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst))))
1966 MainInst = &Inst;
1967 }
1968
1969 joinOperandTree(UnionFind, ModeledInsts);
1970 joinOrderedInstructions(UnionFind, ModeledInsts);
1971 joinOrderedPHIs(UnionFind, ModeledInsts);
1972
1973 // The list of instructions for statement (statement represented by the leader
1974 // instruction).
1975 MapVector<Instruction *, std::vector<Instruction *>> LeaderToInstList;
1976
1977 // The order of statements must be preserved w.r.t. their ordered
1978 // instructions. Without this explicit scan, we would also use non-ordered
1979 // instructions (whose order is arbitrary) to determine statement order.
1980 for (Instruction *Inst : ModeledInsts) {
1981 if (!isOrderedInstruction(Inst))
1982 continue;
1983
1984 auto LeaderIt = UnionFind.findLeader(Inst);
1985 if (LeaderIt == UnionFind.member_end())
1986 continue;
1987
1988 // Insert element for the leader instruction.
1989 (void)LeaderToInstList[*LeaderIt];
1990 }
1991
1992 // Collect the instructions of all leaders. UnionFind's member iterator
1993 // unfortunately are not in any specific order.
1994 for (Instruction *Inst : ModeledInsts) {
1995 auto LeaderIt = UnionFind.findLeader(Inst);
1996 if (LeaderIt == UnionFind.member_end())
1997 continue;
1998
1999 if (Inst == MainInst)
2000 MainLeader = *LeaderIt;
2001 std::vector<Instruction *> &InstList = LeaderToInstList[*LeaderIt];
2002 InstList.push_back(Inst);
2003 }
2004
2005 // Finally build the statements.
2006 int Count = 0;
2007 long BBIdx = scop->getNextStmtIdx();
2008 for (auto &Instructions : LeaderToInstList) {
2009 std::vector<Instruction *> &InstList = Instructions.second;
2010
2011 // If there is no main instruction, make the first statement the main.
2012 bool IsMain = (MainInst ? MainLeader == Instructions.first : Count == 0);
2013
2014 std::string Name = makeStmtName(BB, BBIdx, Count, IsMain);
2015 scop->addScopStmt(BB, Name, L, std::move(InstList));
2016 Count += 1;
2017 }
2018
2019 // Unconditionally add an epilogue (last statement). It contains no
2020 // instructions, but holds the PHI write accesses for successor basic blocks,
2021 // if the incoming value is not defined in another statement if the same BB.
2022 // The epilogue becomes the main statement only if there is no other
2023 // statement that could become main.
2024 // The epilogue will be removed if no PHIWrite is added to it.
2025 std::string EpilogueName = makeStmtName(BB, BBIdx, Count, Count == 0, true);
2026 scop->addScopStmt(BB, EpilogueName, L, {});
2027}
2028
2029void ScopBuilder::buildStmts(Region &SR) {
2030 if (scop->isNonAffineSubRegion(&SR)) {
2031 std::vector<Instruction *> Instructions;
2032 Loop *SurroundingLoop =
2033 getFirstNonBoxedLoopFor(SR.getEntry(), LI, scop->getBoxedLoops());
2034 for (Instruction &Inst : *SR.getEntry())
2035 if (shouldModelInst(&Inst, SurroundingLoop))
2036 Instructions.push_back(&Inst);
2037 long RIdx = scop->getNextStmtIdx();
2038 std::string Name = makeStmtName(&SR, RIdx);
2039 scop->addScopStmt(&SR, Name, SurroundingLoop, Instructions);
2040 return;
2041 }
2042
2043 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
2044 if (I->isSubRegion())
2045 buildStmts(*I->getNodeAs<Region>());
2046 else {
2047 BasicBlock *BB = I->getNodeAs<BasicBlock>();
2048 switch (StmtGranularity) {
2051 break;
2054 break;
2056 buildSequentialBlockStmts(BB, true);
2057 break;
2058 }
2059 }
2060}
2061
2063 Region *NonAffineSubRegion) {
2064 assert(
2065 Stmt &&
2066 "The exit BB is the only one that cannot be represented by a statement");
2067 assert(Stmt->represents(&BB));
2068
2069 // We do not build access functions for error blocks, as they may contain
2070 // instructions we can not model.
2071 if (SD.isErrorBlock(BB, scop->getRegion()))
2072 return;
2073
2074 auto BuildAccessesForInst = [this, Stmt,
2075 NonAffineSubRegion](Instruction *Inst) {
2076 PHINode *PHI = dyn_cast<PHINode>(Inst);
2077 if (PHI)
2078 buildPHIAccesses(Stmt, PHI, NonAffineSubRegion, false);
2079
2080 if (auto MemInst = MemAccInst::dyn_cast(*Inst)) {
2081 assert(Stmt && "Cannot build access function in non-existing statement");
2082 buildMemoryAccess(MemInst, Stmt);
2083 }
2084
2085 // PHI nodes have already been modeled above and terminators that are
2086 // not part of a non-affine subregion are fully modeled and regenerated
2087 // from the polyhedral domains. Hence, they do not need to be modeled as
2088 // explicit data dependences.
2089 if (!PHI)
2090 buildScalarDependences(Stmt, Inst);
2091 };
2092
2093 const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
2094 bool IsEntryBlock = (Stmt->getEntryBlock() == &BB);
2095 if (IsEntryBlock) {
2096 for (Instruction *Inst : Stmt->getInstructions())
2097 BuildAccessesForInst(Inst);
2098 if (Stmt->isRegionStmt())
2099 BuildAccessesForInst(BB.getTerminator());
2100 } else {
2101 for (Instruction &Inst : BB) {
2102 if (isIgnoredIntrinsic(&Inst))
2103 continue;
2104
2105 // Invariant loads already have been processed.
2106 if (isa<LoadInst>(Inst) && RIL.count(cast<LoadInst>(&Inst)))
2107 continue;
2108
2109 BuildAccessesForInst(&Inst);
2110 }
2111 }
2112}
2113
2115 ScopStmt *Stmt, Instruction *Inst, MemoryAccess::AccessType AccType,
2116 Value *BaseAddress, Type *ElementType, bool Affine, Value *AccessValue,
2117 ArrayRef<const SCEV *> Subscripts, ArrayRef<const SCEV *> Sizes,
2118 MemoryKind Kind) {
2119 bool isKnownMustAccess = false;
2120
2121 // Accesses in single-basic block statements are always executed.
2122 if (Stmt->isBlockStmt())
2123 isKnownMustAccess = true;
2124
2125 if (Stmt->isRegionStmt()) {
2126 // Accesses that dominate the exit block of a non-affine region are always
2127 // executed. In non-affine regions there may exist MemoryKind::Values that
2128 // do not dominate the exit. MemoryKind::Values will always dominate the
2129 // exit and MemoryKind::PHIs only if there is at most one PHI_WRITE in the
2130 // non-affine region.
2131 if (Inst && DT.dominates(Inst->getParent(), Stmt->getRegion()->getExit()))
2132 isKnownMustAccess = true;
2133 }
2134
2135 // Non-affine PHI writes do not "happen" at a particular instruction, but
2136 // after exiting the statement. Therefore they are guaranteed to execute and
2137 // overwrite the old value.
2139 isKnownMustAccess = true;
2140
2141 if (!isKnownMustAccess && AccType == MemoryAccess::MUST_WRITE)
2142 AccType = MemoryAccess::MAY_WRITE;
2143
2144 auto *Access = new MemoryAccess(Stmt, Inst, AccType, BaseAddress, ElementType,
2145 Affine, Subscripts, Sizes, AccessValue, Kind);
2146
2147 scop->addAccessFunction(Access);
2148 Stmt->addAccess(Access);
2149 return Access;
2150}
2151
2154 Value *BaseAddress, Type *ElementType,
2155 bool IsAffine,
2156 ArrayRef<const SCEV *> Subscripts,
2157 ArrayRef<const SCEV *> Sizes,
2158 Value *AccessValue) {
2159 ArrayBasePointers.insert(BaseAddress);
2160 addMemoryAccess(Stmt, MemAccInst, AccType, BaseAddress, ElementType, IsAffine,
2161 AccessValue, Subscripts, Sizes, MemoryKind::Array);
2162}
2163
2164/// Check if @p Expr is divisible by @p Size.
2165static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) {
2166 assert(Size != 0);
2167 if (Size == 1)
2168 return true;
2169
2170 // Only one factor needs to be divisible.
2171 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
2172 for (const SCEV *FactorExpr : MulExpr->operands())
2173 if (isDivisible(FactorExpr, Size, SE))
2174 return true;
2175 return false;
2176 }
2177
2178 // For other n-ary expressions (Add, AddRec, Max,...) all operands need
2179 // to be divisible.
2180 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
2181 for (const SCEV *OpExpr : NAryExpr->operands())
2182 if (!isDivisible(OpExpr, Size, SE))
2183 return false;
2184 return true;
2185 }
2186
2187 const SCEV *SizeSCEV = SE.getConstant(Expr->getType(), Size);
2188 const SCEV *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
2189 const SCEV *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
2190 return MulSCEV == Expr;
2191}
2192
2194 isl::union_set Accessed = scop->getAccesses().range();
2195
2196 for (auto Array : scop->arrays()) {
2197 if (Array->getNumberOfDimensions() <= 1)
2198 continue;
2199
2200 isl::space Space = Array->getSpace();
2201 Space = Space.align_params(Accessed.get_space());
2202
2203 if (!Accessed.contains(Space))
2204 continue;
2205
2206 isl::set Elements = Accessed.extract_set(Space);
2207 isl::map Transform = isl::map::universe(Array->getSpace().map_from_set());
2208
2209 std::vector<int> Int;
2210 unsigned Dims = unsignedFromIslSize(Elements.tuple_dim());
2211 for (unsigned i = 0; i < Dims; i++) {
2212 isl::set DimOnly = isl::set(Elements).project_out(isl::dim::set, 0, i);
2213 DimOnly = DimOnly.project_out(isl::dim::set, 1, Dims - i - 1);
2214 DimOnly = DimOnly.lower_bound_si(isl::dim::set, 0, 0);
2215
2216 isl::basic_set DimHull = DimOnly.affine_hull();
2217
2218 if (i == Dims - 1) {
2219 Int.push_back(1);
2220 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
2221 continue;
2222 }
2223
2224 if (unsignedFromIslSize(DimHull.dim(isl::dim::div)) == 1) {
2225 isl::aff Diff = DimHull.get_div(0);
2226 isl::val Val = Diff.get_denominator_val();
2227
2228 int ValInt = 1;
2229 if (Val.is_int()) {
2230 auto ValAPInt = APIntFromVal(Val);
2231 if (ValAPInt.isSignedIntN(32))
2232 ValInt = ValAPInt.getSExtValue();
2233 } else {
2234 }
2235
2236 Int.push_back(ValInt);
2238 isl::local_space(Transform.get_space()));
2239 C = C.set_coefficient_si(isl::dim::out, i, ValInt);
2240 C = C.set_coefficient_si(isl::dim::in, i, -1);
2241 Transform = Transform.add_constraint(C);
2242 continue;
2243 }
2244
2245 isl::basic_set ZeroSet = isl::basic_set(DimHull);
2246 ZeroSet = ZeroSet.fix_si(isl::dim::set, 0, 0);
2247
2248 int ValInt = 1;
2249 if (ZeroSet.is_equal(DimHull)) {
2250 ValInt = 0;
2251 }
2252
2253 Int.push_back(ValInt);
2254 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
2255 }
2256
2257 isl::set MappedElements = isl::map(Transform).domain();
2258 if (!Elements.is_subset(MappedElements))
2259 continue;
2260
2261 bool CanFold = true;
2262 if (Int[0] <= 1)
2263 CanFold = false;
2264
2265 unsigned NumDims = Array->getNumberOfDimensions();
2266 for (unsigned i = 1; i < NumDims - 1; i++)
2267 if (Int[0] != Int[i] && Int[i])
2268 CanFold = false;
2269
2270 if (!CanFold)
2271 continue;
2272
2273 for (auto &Access : scop->access_functions())
2274 if (Access->getScopArrayInfo() == Array)
2275 Access->setAccessRelation(
2276 Access->getAccessRelation().apply_range(Transform));
2277
2278 std::vector<const SCEV *> Sizes;
2279 for (unsigned i = 0; i < NumDims; i++) {
2280 auto Size = Array->getDimensionSize(i);
2281
2282 if (i == NumDims - 1)
2283 Size = SE.getMulExpr(Size, SE.getConstant(Size->getType(), Int[0]));
2284 Sizes.push_back(Size);
2285 }
2286
2287 Array->updateSizes(Sizes, false /* CheckConsistency */);
2288 }
2289}
2290
2297
2299 // Check all array accesses for each base pointer and find a (virtual) element
2300 // size for the base pointer that divides all access functions.
2301 for (ScopStmt &Stmt : *scop)
2302 for (MemoryAccess *Access : Stmt) {
2303 if (!Access->isArrayKind())
2304 continue;
2306 const_cast<ScopArrayInfo *>(Access->getScopArrayInfo());
2307
2308 if (Array->getNumberOfDimensions() != 1)
2309 continue;
2310 unsigned DivisibleSize = Array->getElemSizeInBytes();
2311 const SCEV *Subscript = Access->getSubscript(0);
2312 while (!isDivisible(Subscript, DivisibleSize, SE))
2313 DivisibleSize /= 2;
2314 auto *Ty = IntegerType::get(SE.getContext(), DivisibleSize * 8);
2315 Array->updateElementType(Ty);
2316 }
2317
2318 for (auto &Stmt : *scop)
2319 for (auto &Access : Stmt)
2320 Access->updateDimensionality();
2321}
2322
2324 for (auto &Stmt : *scop)
2325 for (auto &Access : Stmt)
2326 Access->foldAccessRelation();
2327}
2328
2331 return;
2332 for (auto &Stmt : *scop)
2333 for (auto &Access : Stmt) {
2334 isl::set Outside = Access->assumeNoOutOfBound();
2335 const auto &Loc = Access->getAccessInstruction()
2336 ? Access->getAccessInstruction()->getDebugLoc()
2337 : DebugLoc();
2340 }
2341}
2342
2343void ScopBuilder::ensureValueWrite(Instruction *Inst) {
2344 // Find the statement that defines the value of Inst. That statement has to
2345 // write the value to make it available to those statements that read it.
2346 ScopStmt *Stmt = scop->getStmtFor(Inst);
2347
2348 // It is possible that the value is synthesizable within a loop (such that it
2349 // is not part of any statement), but not after the loop (where you need the
2350 // number of loop round-trips to synthesize it). In LCSSA-form a PHI node will
2351 // avoid this. In case the IR has no such PHI, use the last statement (where
2352 // the value is synthesizable) to write the value.
2353 if (!Stmt)
2354 Stmt = scop->getLastStmtFor(Inst->getParent());
2355
2356 // Inst not defined within this SCoP.
2357 if (!Stmt)
2358 return;
2359
2360 // Do not process further if the instruction is already written.
2361 if (Stmt->lookupValueWriteOf(Inst))
2362 return;
2363
2364 addMemoryAccess(Stmt, Inst, MemoryAccess::MUST_WRITE, Inst, Inst->getType(),
2365 true, Inst, ArrayRef<const SCEV *>(),
2366 ArrayRef<const SCEV *>(), MemoryKind::Value);
2367}
2368
2370 // TODO: Make ScopStmt::ensureValueRead(Value*) offer the same functionality
2371 // to be able to replace this one. Currently, there is a split responsibility.
2372 // In a first step, the MemoryAccess is created, but without the
2373 // AccessRelation. In the second step by ScopStmt::buildAccessRelations(), the
2374 // AccessRelation is created. At least for scalar accesses, there is no new
2375 // information available at ScopStmt::buildAccessRelations(), so we could
2376 // create the AccessRelation right away. This is what
2377 // ScopStmt::ensureValueRead(Value*) does.
2378
2379 auto *Scope = UserStmt->getSurroundingLoop();
2380 auto VUse = VirtualUse::create(scop.get(), UserStmt, Scope, V, false);
2381 switch (VUse.getKind()) {
2383 case VirtualUse::Block:
2386 case VirtualUse::Intra:
2387 // Uses of these kinds do not need a MemoryAccess.
2388 break;
2389
2391 // Add MemoryAccess for invariant values only if requested.
2393 break;
2394
2395 [[fallthrough]];
2396 case VirtualUse::Inter:
2397
2398 // Do not create another MemoryAccess for reloading the value if one already
2399 // exists.
2400 if (UserStmt->lookupValueReadOf(V))
2401 break;
2402
2403 addMemoryAccess(UserStmt, nullptr, MemoryAccess::READ, V, V->getType(),
2404 true, V, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2406
2407 // Inter-statement uses need to write the value in their defining statement.
2408 if (VUse.isInter())
2409 ensureValueWrite(cast<Instruction>(V));
2410 break;
2411 }
2412}
2413
2414void ScopBuilder::ensurePHIWrite(PHINode *PHI, ScopStmt *IncomingStmt,
2415 BasicBlock *IncomingBlock,
2416 Value *IncomingValue, bool IsExitBlock) {
2417 // As the incoming block might turn out to be an error statement ensure we
2418 // will create an exit PHI SAI object. It is needed during code generation
2419 // and would be created later anyway.
2420 if (IsExitBlock)
2421 scop->getOrCreateScopArrayInfo(PHI, PHI->getType(), {},
2423
2424 // This is possible if PHI is in the SCoP's entry block. The incoming blocks
2425 // from outside the SCoP's region have no statement representation.
2426 if (!IncomingStmt)
2427 return;
2428
2429 // Take care for the incoming value being available in the incoming block.
2430 // This must be done before the check for multiple PHI writes because multiple
2431 // exiting edges from subregion each can be the effective written value of the
2432 // subregion. As such, all of them must be made available in the subregion
2433 // statement.
2434 ensureValueRead(IncomingValue, IncomingStmt);
2435
2436 // Do not add more than one MemoryAccess per PHINode and ScopStmt.
2437 if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) {
2438 assert(Acc->getAccessInstruction() == PHI);
2439 Acc->addIncoming(IncomingBlock, IncomingValue);
2440 return;
2441 }
2442
2444 IncomingStmt, PHI, MemoryAccess::MUST_WRITE, PHI, PHI->getType(), true,
2445 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2446 IsExitBlock ? MemoryKind::ExitPHI : MemoryKind::PHI);
2447 assert(Acc);
2448 Acc->addIncoming(IncomingBlock, IncomingValue);
2449}
2450
2452 addMemoryAccess(PHIStmt, PHI, MemoryAccess::READ, PHI, PHI->getType(), true,
2453 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2455}
2456
2458 isl::id Id = isl::id::alloc(scop->getIslCtx(), Stmt.getBaseName(), &Stmt);
2459
2460 Stmt.Domain = scop->getDomainConditions(&Stmt);
2461 Stmt.Domain = Stmt.Domain.set_tuple_id(Id);
2462}
2463
2465 isl::set Domain = Stmt.getDomain();
2466 BasicBlock *BB = Stmt.getEntryBlock();
2467
2468 Loop *L = LI.getLoopFor(BB);
2469
2470 while (L && Stmt.isRegionStmt() && Stmt.getRegion()->contains(L))
2471 L = L->getParentLoop();
2472
2473 SmallVector<llvm::Loop *, 8> Loops;
2474
2475 while (L && Stmt.getParent()->getRegion().contains(L)) {
2476 Loops.push_back(L);
2477 L = L->getParentLoop();
2478 }
2479
2480 Stmt.NestLoops.insert(Stmt.NestLoops.begin(), Loops.rbegin(), Loops.rend());
2481}
2482
2483/// Return the reduction type for a given binary operator.
2485getReductionType(const BinaryOperator *BinOp) {
2486 if (!BinOp)
2487 return MemoryAccess::RT_NONE;
2488 switch (BinOp->getOpcode()) {
2489 case Instruction::FAdd:
2490 if (!BinOp->isFast())
2491 return MemoryAccess::RT_NONE;
2492 [[fallthrough]];
2493 case Instruction::Add:
2494 return MemoryAccess::RT_ADD;
2495 case Instruction::Or:
2496 return MemoryAccess::RT_BOR;
2497 case Instruction::Xor:
2498 return MemoryAccess::RT_BXOR;
2499 case Instruction::And:
2500 return MemoryAccess::RT_BAND;
2501 case Instruction::FMul:
2502 if (!BinOp->isFast())
2503 return MemoryAccess::RT_NONE;
2504 [[fallthrough]];
2505 case Instruction::Mul:
2507 return MemoryAccess::RT_NONE;
2508 return MemoryAccess::RT_MUL;
2509 default:
2510 return MemoryAccess::RT_NONE;
2511 }
2512}
2513
2514/// @brief Combine two reduction types
2518 if (RT0 == MemoryAccess::RT_BOTTOM)
2519 return RT1;
2520 if (RT0 == RT1)
2521 return RT1;
2522 return MemoryAccess::RT_NONE;
2523}
2524
2525/// True if @p AllAccs intersects with @p MemAccs except @p LoadMA and @p
2526/// StoreMA
2528 MemoryAccess *StoreMA, isl::set Domain,
2529 SmallVector<MemoryAccess *, 8> &MemAccs) {
2530 bool HasIntersectingAccs = false;
2531 auto AllAccsNoParams = AllAccs.project_out_all_params();
2532
2533 for (MemoryAccess *MA : MemAccs) {
2534 if (MA == LoadMA || MA == StoreMA)
2535 continue;
2536 auto AccRel = MA->getAccessRelation().intersect_domain(Domain);
2537 auto Accs = AccRel.range();
2538 auto AccsNoParams = Accs.project_out_all_params();
2539
2540 bool CompatibleSpace = AllAccsNoParams.has_equal_space(AccsNoParams);
2541
2542 if (CompatibleSpace) {
2543 auto OverlapAccs = Accs.intersect(AllAccs);
2544 bool DoesIntersect = !OverlapAccs.is_empty();
2545 HasIntersectingAccs |= DoesIntersect;
2546 }
2547 }
2548 return HasIntersectingAccs;
2549}
2550
2551/// Test if the accesses of @p LoadMA and @p StoreMA can form a reduction
2554 SmallVector<MemoryAccess *, 8> &MemAccs) {
2555 // First check if the base value is the same.
2556 isl::map LoadAccs = LoadMA->getAccessRelation();
2557 isl::map StoreAccs = StoreMA->getAccessRelation();
2558 bool Valid = LoadAccs.has_equal_space(StoreAccs);
2559 POLLY_DEBUG(dbgs() << " == The accessed space below is "
2560 << (Valid ? "" : "not ") << "equal!\n");
2561 POLLY_DEBUG(LoadMA->dump(); StoreMA->dump());
2562
2563 if (Valid) {
2564 // Then check if they actually access the same memory.
2565 isl::map R = isl::manage(LoadAccs.copy())
2566 .intersect_domain(isl::manage(Domain.copy()));
2567 isl::map W = isl::manage(StoreAccs.copy())
2568 .intersect_domain(isl::manage(Domain.copy()));
2569 isl::set RS = R.range();
2570 isl::set WS = W.range();
2571
2572 isl::set InterAccs =
2573 isl::manage(RS.copy()).intersect(isl::manage(WS.copy()));
2574 Valid = !InterAccs.is_empty();
2575 POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "" : "not ")
2576 << "overlapping!\n");
2577 }
2578
2579 if (Valid) {
2580 // Finally, check if they are no other instructions accessing this memory
2581 isl::map AllAccsRel = LoadAccs.unite(StoreAccs);
2582 AllAccsRel = AllAccsRel.intersect_domain(Domain);
2583 isl::set AllAccs = AllAccsRel.range();
2584 Valid = !hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs);
2585 POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "")
2586 << "accessed by other instructions!\n");
2587 }
2588
2589 return Valid;
2590}
2591
2593 // Perform a data flow analysis on the current scop statement to propagate the
2594 // uses of loaded values. Then check and mark the memory accesses which are
2595 // part of reduction like chains.
2596 // During the data flow analysis we use the State variable to keep track of
2597 // the used "load-instructions" for each instruction in the scop statement.
2598 // This includes the LLVM-IR of the load and the "number of uses" (or the
2599 // number of paths in the operand tree which end in this load).
2600 using StatePairTy = std::pair<unsigned, MemoryAccess::ReductionType>;
2601 using FlowInSetTy = MapVector<const LoadInst *, StatePairTy>;
2602 using StateTy = MapVector<const Instruction *, FlowInSetTy>;
2603 StateTy State;
2604
2605 // Invalid loads are loads which have uses we can't track properly in the
2606 // state map. This includes loads which:
2607 // o do not form a reduction when they flow into a memory location:
2608 // (e.g., A[i] = B[i] * 3 and A[i] = A[i] * A[i] + A[i])
2609 // o are used by a non binary operator or one which is not commutative
2610 // and associative (e.g., A[i] = A[i] % 3)
2611 // o might change the control flow (e.g., if (A[i]))
2612 // o are used in indirect memory accesses (e.g., A[B[i]])
2613 // o are used outside the current scop statement
2614 SmallPtrSet<const Instruction *, 8> InvalidLoads;
2615 SmallVector<BasicBlock *, 8> ScopBlocks;
2616 BasicBlock *BB = Stmt.getBasicBlock();
2617 if (BB)
2618 ScopBlocks.push_back(BB);
2619 else
2620 for (BasicBlock *Block : Stmt.getRegion()->blocks())
2621 ScopBlocks.push_back(Block);
2622 // Run the data flow analysis for all values in the scop statement
2623 for (BasicBlock *Block : ScopBlocks) {
2624 for (Instruction &Inst : *Block) {
2625 if ((Stmt.getParent())->getStmtFor(&Inst) != &Stmt)
2626 continue;
2627 bool UsedOutsideStmt = any_of(Inst.users(), [&Stmt](User *U) {
2628 return (Stmt.getParent())->getStmtFor(cast<Instruction>(U)) != &Stmt;
2629 });
2630 // Treat loads and stores special
2631 if (auto *Load = dyn_cast<LoadInst>(&Inst)) {
2632 // Invalidate all loads used which feed into the address of this load.
2633 if (auto *Ptr = dyn_cast<Instruction>(Load->getPointerOperand())) {
2634 const auto &It = State.find(Ptr);
2635 if (It != State.end())
2636 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2637 }
2638
2639 // If this load is used outside this stmt, invalidate it.
2640 if (UsedOutsideStmt)
2641 InvalidLoads.insert(Load);
2642
2643 // And indicate that this load uses itself once but without specifying
2644 // any reduction operator.
2645 State[Load].insert(
2646 std::make_pair(Load, std::make_pair(1, MemoryAccess::RT_BOTTOM)));
2647 continue;
2648 }
2649
2650 if (auto *Store = dyn_cast<StoreInst>(&Inst)) {
2651 // Invalidate all loads which feed into the address of this store.
2652 if (const Instruction *Ptr =
2653 dyn_cast<Instruction>(Store->getPointerOperand())) {
2654 const auto &It = State.find(Ptr);
2655 if (It != State.end())
2656 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2657 }
2658
2659 // Propagate the uses of the value operand to the store
2660 if (auto *ValueInst = dyn_cast<Instruction>(Store->getValueOperand()))
2661 State.insert(std::make_pair(Store, State[ValueInst]));
2662 continue;
2663 }
2664
2665 // Non load and store instructions are either binary operators or they
2666 // will invalidate all used loads.
2667 auto *BinOp = dyn_cast<BinaryOperator>(&Inst);
2669 POLLY_DEBUG(dbgs() << "CurInst: " << Inst << " RT: " << CurRedType
2670 << "\n");
2671
2672 // Iterate over all operands and propagate their input loads to
2673 // instruction.
2674 FlowInSetTy &InstInFlowSet = State[&Inst];
2675 for (Use &Op : Inst.operands()) {
2676 auto *OpInst = dyn_cast<Instruction>(Op);
2677 if (!OpInst)
2678 continue;
2679
2680 POLLY_DEBUG(dbgs().indent(4) << "Op Inst: " << *OpInst << "\n");
2681 const StateTy::iterator &OpInFlowSetIt = State.find(OpInst);
2682 if (OpInFlowSetIt == State.end())
2683 continue;
2684
2685 // Iterate over all the input loads of the operand and combine them
2686 // with the input loads of current instruction.
2687 FlowInSetTy &OpInFlowSet = OpInFlowSetIt->second;
2688 for (auto &OpInFlowPair : OpInFlowSet) {
2689 unsigned OpFlowIn = OpInFlowPair.second.first;
2690 unsigned InstFlowIn = InstInFlowSet[OpInFlowPair.first].first;
2691
2692 MemoryAccess::ReductionType OpRedType = OpInFlowPair.second.second;
2693 MemoryAccess::ReductionType InstRedType =
2694 InstInFlowSet[OpInFlowPair.first].second;
2695
2696 MemoryAccess::ReductionType NewRedType =
2697 combineReductionType(OpRedType, CurRedType);
2698 if (InstFlowIn)
2699 NewRedType = combineReductionType(NewRedType, InstRedType);
2700
2701 POLLY_DEBUG(dbgs().indent(8) << "OpRedType: " << OpRedType << "\n");
2702 POLLY_DEBUG(dbgs().indent(8) << "NewRedType: " << NewRedType << "\n");
2703 InstInFlowSet[OpInFlowPair.first] =
2704 std::make_pair(OpFlowIn + InstFlowIn, NewRedType);
2705 }
2706 }
2707
2708 // If this operation is used outside the stmt, invalidate all the loads
2709 // which feed into it.
2710 if (UsedOutsideStmt)
2711 InvalidLoads.insert_range(llvm::make_first_range(InstInFlowSet));
2712 }
2713 }
2714
2715 // All used loads are propagated through the whole basic block; now try to
2716 // find valid reduction-like candidate pairs. These load-store pairs fulfill
2717 // all reduction like properties with regards to only this load-store chain.
2718 // We later have to check if the loaded value was invalidated by an
2719 // instruction not in that chain.
2720 using MemAccPair = std::pair<MemoryAccess *, MemoryAccess *>;
2721 DenseMap<MemAccPair, MemoryAccess::ReductionType> ValidCandidates;
2722
2723 // Iterate over all write memory accesses and check the loads flowing into
2724 // it for reduction candidate pairs.
2725 for (MemoryAccess *WriteMA : Stmt.MemAccs) {
2726 if (WriteMA->isRead())
2727 continue;
2728 StoreInst *St = dyn_cast<StoreInst>(WriteMA->getAccessInstruction());
2729 if (!St)
2730 continue;
2731 assert(!St->isVolatile());
2732
2733 FlowInSetTy &MaInFlowSet = State[WriteMA->getAccessInstruction()];
2734 for (auto &MaInFlowSetElem : MaInFlowSet) {
2735 MemoryAccess *ReadMA = &Stmt.getArrayAccessFor(MaInFlowSetElem.first);
2736 assert(ReadMA && "Couldn't find memory access for incoming load!");
2737
2738 POLLY_DEBUG(dbgs() << "'" << *ReadMA->getAccessInstruction()
2739 << "'\n\tflows into\n'"
2740 << *WriteMA->getAccessInstruction() << "'\n\t #"
2741 << MaInFlowSetElem.second.first << " times & RT: "
2742 << MaInFlowSetElem.second.second << "\n");
2743
2744 MemoryAccess::ReductionType RT = MaInFlowSetElem.second.second;
2745 unsigned NumAllowableInFlow = 1;
2746
2747 // We allow the load to flow in exactly once for binary reductions
2748 bool Valid = (MaInFlowSetElem.second.first == NumAllowableInFlow);
2749
2750 // Check if we saw a valid chain of binary operators.
2751 Valid = Valid && RT != MemoryAccess::RT_BOTTOM;
2752 Valid = Valid && RT != MemoryAccess::RT_NONE;
2753
2754 // Then check if the memory accesses allow a reduction.
2755 Valid = Valid && checkCandidatePairAccesses(
2756 ReadMA, WriteMA, Stmt.getDomain(), Stmt.MemAccs);
2757
2758 // Finally, mark the pair as a candidate or the load as a invalid one.
2759 if (Valid)
2760 ValidCandidates[std::make_pair(ReadMA, WriteMA)] = RT;
2761 else
2762 InvalidLoads.insert(ReadMA->getAccessInstruction());
2763 }
2764 }
2765
2766 // In the last step mark the memory accesses of candidate pairs as reduction
2767 // like if the load wasn't marked invalid in the previous step.
2768 for (auto &CandidatePair : ValidCandidates) {
2769 MemoryAccess *LoadMA = CandidatePair.first.first;
2770 if (InvalidLoads.count(LoadMA->getAccessInstruction()))
2771 continue;
2773 dbgs() << " Load :: "
2774 << *((CandidatePair.first.first)->getAccessInstruction())
2775 << "\n Store :: "
2776 << *((CandidatePair.first.second)->getAccessInstruction())
2777 << "\n are marked as reduction like\n");
2778 MemoryAccess::ReductionType RT = CandidatePair.second;
2779 CandidatePair.first.first->markAsReductionLike(RT);
2780 CandidatePair.first.second->markAsReductionLike(RT);
2781 }
2782}
2783
2785 auto &RIL = scop->getRequiredInvariantLoads();
2786 for (LoadInst *LI : RIL) {
2787 assert(LI && scop->contains(LI));
2788 // If there exists a statement in the scop which has a memory access for
2789 // @p LI, then mark this scop as infeasible for optimization.
2790 for (ScopStmt &Stmt : *scop)
2791 if (Stmt.getArrayAccessOrNULLFor(LI)) {
2792 scop->invalidate(INVARIANTLOAD, LI->getDebugLoc(), LI->getParent());
2793 return;
2794 }
2795 }
2796}
2797
2800 return;
2801
2802 isl::union_map Writes = scop->getWrites();
2803 for (ScopStmt &Stmt : *scop) {
2804 InvariantAccessesTy InvariantAccesses;
2805
2806 for (MemoryAccess *Access : Stmt) {
2807 isl::set NHCtx = getNonHoistableCtx(Access, Writes);
2808 if (!NHCtx.is_null())
2809 InvariantAccesses.push_back({Access, NHCtx});
2810 }
2811
2812 // Transfer the memory access from the statement to the SCoP.
2813 for (auto InvMA : InvariantAccesses)
2814 Stmt.removeMemoryAccess(InvMA.MA);
2815 addInvariantLoads(Stmt, InvariantAccesses);
2816 }
2817}
2818
2819/// Check if an access range is too complex.
2820///
2821/// An access range is too complex, if it contains either many disjuncts or
2822/// very complex expressions. As a simple heuristic, we assume if a set to
2823/// be too complex if the sum of existentially quantified dimensions and
2824/// set dimensions is larger than a threshold. This reliably detects both
2825/// sets with many disjuncts as well as sets with many divisions as they
2826/// arise in h264.
2827///
2828/// @param AccessRange The range to check for complexity.
2829///
2830/// @returns True if the access range is too complex.
2831static bool isAccessRangeTooComplex(isl::set AccessRange) {
2832 unsigned NumTotalDims = 0;
2833
2834 for (isl::basic_set BSet : AccessRange.get_basic_set_list()) {
2835 NumTotalDims += unsignedFromIslSize(BSet.dim(isl::dim::div));
2836 NumTotalDims += unsignedFromIslSize(BSet.dim(isl::dim::set));
2837 }
2838
2839 if (NumTotalDims > MaxDimensionsInAccessRange)
2840 return true;
2841
2842 return false;
2843}
2844
2846 isl::union_map Writes) {
2847 if (auto *BasePtrMA = scop->lookupBasePtrAccess(MA)) {
2848 return getNonHoistableCtx(BasePtrMA, Writes).is_null();
2849 }
2850
2851 Value *BaseAddr = MA->getOriginalBaseAddr();
2852 if (auto *BasePtrInst = dyn_cast<Instruction>(BaseAddr))
2853 if (!isa<LoadInst>(BasePtrInst))
2854 return scop->contains(BasePtrInst);
2855
2856 return false;
2857}
2858
2860 if (UserContextStr.empty())
2861 return;
2862
2863 isl::set UserContext = isl::set(scop->getIslCtx(), UserContextStr.c_str());
2864 isl::space Space = scop->getParamSpace();
2865 isl::size SpaceParams = Space.dim(isl::dim::param);
2866 if (unsignedFromIslSize(SpaceParams) !=
2867 unsignedFromIslSize(UserContext.dim(isl::dim::param))) {
2868 std::string SpaceStr = stringFromIslObj(Space, "null");
2869 errs() << "Error: the context provided in -polly-context has not the same "
2870 << "number of dimensions than the computed context. Due to this "
2871 << "mismatch, the -polly-context option is ignored. Please provide "
2872 << "the context in the parameter space: " << SpaceStr << ".\n";
2873 return;
2874 }
2875
2876 for (auto i : rangeIslSize(0, SpaceParams)) {
2877 std::string NameContext =
2878 scop->getContext().get_dim_name(isl::dim::param, i);
2879 std::string NameUserContext = UserContext.get_dim_name(isl::dim::param, i);
2880
2881 if (NameContext != NameUserContext) {
2882 std::string SpaceStr = stringFromIslObj(Space, "null");
2883 errs() << "Error: the name of dimension " << i
2884 << " provided in -polly-context "
2885 << "is '" << NameUserContext << "', but the name in the computed "
2886 << "context is '" << NameContext
2887 << "'. Due to this name mismatch, "
2888 << "the -polly-context option is ignored. Please provide "
2889 << "the context in the parameter space: " << SpaceStr << ".\n";
2890 return;
2891 }
2892
2893 UserContext = UserContext.set_dim_id(isl::dim::param, i,
2894 Space.get_dim_id(isl::dim::param, i));
2895 }
2896 isl::set newContext = scop->getContext().intersect(UserContext);
2897 scop->setContext(newContext);
2898}
2899
2901 isl::union_map Writes) {
2902 // TODO: Loads that are not loop carried, hence are in a statement with
2903 // zero iterators, are by construction invariant, though we
2904 // currently "hoist" them anyway. This is necessary because we allow
2905 // them to be treated as parameters (e.g., in conditions) and our code
2906 // generation would otherwise use the old value.
2907
2908 auto &Stmt = *Access->getStatement();
2909 BasicBlock *BB = Stmt.getEntryBlock();
2910
2911 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine() ||
2912 Access->isMemoryIntrinsic())
2913 return {};
2914
2915 // Skip accesses that have an invariant base pointer which is defined but
2916 // not loaded inside the SCoP. This can happened e.g., if a readnone call
2917 // returns a pointer that is used as a base address. However, as we want
2918 // to hoist indirect pointers, we allow the base pointer to be defined in
2919 // the region if it is also a memory access. Each ScopArrayInfo object
2920 // that has a base pointer origin has a base pointer that is loaded and
2921 // that it is invariant, thus it will be hoisted too. However, if there is
2922 // no base pointer origin we check that the base pointer is defined
2923 // outside the region.
2924 auto *LI = cast<LoadInst>(Access->getAccessInstruction());
2925 if (hasNonHoistableBasePtrInScop(Access, Writes))
2926 return {};
2927
2928 isl::map AccessRelation = Access->getAccessRelation();
2929 assert(!AccessRelation.is_empty());
2930
2931 if (AccessRelation.involves_dims(isl::dim::in, 0, Stmt.getNumIterators()))
2932 return {};
2933
2934 AccessRelation = AccessRelation.intersect_domain(Stmt.getDomain());
2935 isl::set SafeToLoad;
2936
2937 auto &DL = scop->getFunction().getDataLayout();
2938 if (isSafeToLoadUnconditionally(LI->getPointerOperand(), LI->getType(),
2939 LI->getAlign(), DL, nullptr)) {
2940 SafeToLoad = isl::set::universe(AccessRelation.get_space().range());
2941 } else if (BB != LI->getParent()) {
2942 // Skip accesses in non-affine subregions as they might not be executed
2943 // under the same condition as the entry of the non-affine subregion.
2944 return {};
2945 } else {
2946 SafeToLoad = AccessRelation.range();
2947 }
2948
2949 if (isAccessRangeTooComplex(AccessRelation.range()))
2950 return {};
2951
2952 isl::union_map Written = Writes.intersect_range(SafeToLoad);
2953 isl::set WrittenCtx = Written.params();
2954 bool IsWritten = !WrittenCtx.is_empty();
2955
2956 if (!IsWritten)
2957 return WrittenCtx;
2958
2959 WrittenCtx = WrittenCtx.remove_divs();
2960 bool TooComplex =
2962 if (TooComplex || !isRequiredInvariantLoad(LI))
2963 return {};
2964
2965 scop->addAssumption(INVARIANTLOAD, WrittenCtx, LI->getDebugLoc(),
2966 AS_RESTRICTION, LI->getParent());
2967 return WrittenCtx;
2968}
2969
2970static bool isAParameter(llvm::Value *maybeParam, const Function &F) {
2971 for (const llvm::Argument &Arg : F.args())
2972 if (&Arg == maybeParam)
2973 return true;
2974
2975 return false;
2976}
2977
2979 bool StmtInvalidCtxIsEmpty,
2980 bool MAInvalidCtxIsEmpty,
2981 bool NonHoistableCtxIsEmpty) {
2982 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
2983 const DataLayout &DL = LInst->getDataLayout();
2985 isAParameter(LInst->getPointerOperand(), scop->getFunction()))
2986 return true;
2987
2988 // TODO: We can provide more information for better but more expensive
2989 // results.
2990 if (!isDereferenceableAndAlignedPointer(
2991 LInst->getPointerOperand(), LInst->getType(), LInst->getAlign(), DL))
2992 return false;
2993
2994 // If the location might be overwritten we do not hoist it unconditionally.
2995 //
2996 // TODO: This is probably too conservative.
2997 if (!NonHoistableCtxIsEmpty)
2998 return false;
2999
3000 // If a dereferenceable load is in a statement that is modeled precisely we
3001 // can hoist it.
3002 if (StmtInvalidCtxIsEmpty && MAInvalidCtxIsEmpty)
3003 return true;
3004
3005 // Even if the statement is not modeled precisely we can hoist the load if it
3006 // does not involve any parameters that might have been specialized by the
3007 // statement domain.
3008 for (const SCEV *Subscript : MA->subscripts())
3009 if (!isa<SCEVConstant>(Subscript))
3010 return false;
3011 return true;
3012}
3013
3015 InvariantAccessesTy &InvMAs) {
3016 if (InvMAs.empty())
3017 return;
3018
3019 isl::set StmtInvalidCtx = Stmt.getInvalidContext();
3020 bool StmtInvalidCtxIsEmpty = StmtInvalidCtx.is_empty();
3021
3022 // Get the context under which the statement is executed but remove the error
3023 // context under which this statement is reached.
3024 isl::set DomainCtx = Stmt.getDomain().params();
3025 DomainCtx = DomainCtx.subtract(StmtInvalidCtx);
3026
3028 auto *AccInst = InvMAs.front().MA->getAccessInstruction();
3029 scop->invalidate(COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent());
3030 return;
3031 }
3032
3033 // Project out all parameters that relate to loads in the statement. Otherwise
3034 // we could have cyclic dependences on the constraints under which the
3035 // hoisted loads are executed and we could not determine an order in which to
3036 // pre-load them. This happens because not only lower bounds are part of the
3037 // domain but also upper bounds.
3038 for (auto &InvMA : InvMAs) {
3039 auto *MA = InvMA.MA;
3040 Instruction *AccInst = MA->getAccessInstruction();
3041 if (SE.isSCEVable(AccInst->getType())) {
3042 SetVector<Value *> Values;
3043 for (const SCEV *Parameter : scop->parameters()) {
3044 Values.clear();
3045 findValues(Parameter, SE, Values);
3046 if (!Values.count(AccInst))
3047 continue;
3048
3049 isl::id ParamId = scop->getIdForParam(Parameter);
3050 if (!ParamId.is_null()) {
3051 int Dim = DomainCtx.find_dim_by_id(isl::dim::param, ParamId);
3052 if (Dim >= 0)
3053 DomainCtx = DomainCtx.eliminate(isl::dim::param, Dim, 1);
3054 }
3055 }
3056 }
3057 }
3058
3059 for (auto &InvMA : InvMAs) {
3060 auto *MA = InvMA.MA;
3061 isl::set NHCtx = InvMA.NonHoistableCtx;
3062
3063 // Check for another invariant access that accesses the same location as
3064 // MA and if found consolidate them. Otherwise create a new equivalence
3065 // class at the end of InvariantEquivClasses.
3066 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
3067 Type *Ty = LInst->getType();
3068 const SCEV *PointerSCEV = SE.getSCEV(LInst->getPointerOperand());
3069
3070 isl::set MAInvalidCtx = MA->getInvalidContext();
3071 bool NonHoistableCtxIsEmpty = NHCtx.is_empty();
3072 bool MAInvalidCtxIsEmpty = MAInvalidCtx.is_empty();
3073
3074 isl::set MACtx;
3075 // Check if we know that this pointer can be speculatively accessed.
3076 if (canAlwaysBeHoisted(MA, StmtInvalidCtxIsEmpty, MAInvalidCtxIsEmpty,
3077 NonHoistableCtxIsEmpty)) {
3078 MACtx = isl::set::universe(DomainCtx.get_space());
3079 } else {
3080 MACtx = DomainCtx;
3081 MACtx = MACtx.subtract(MAInvalidCtx.unite(NHCtx));
3082 MACtx = MACtx.gist_params(scop->getContext());
3083 }
3084
3085 bool Consolidated = false;
3086 for (auto &IAClass : scop->invariantEquivClasses()) {
3087 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
3088 continue;
3089
3090 // If the pointer and the type is equal check if the access function wrt.
3091 // to the domain is equal too. It can happen that the domain fixes
3092 // parameter values and these can be different for distinct part of the
3093 // SCoP. If this happens we cannot consolidate the loads but need to
3094 // create a new invariant load equivalence class.
3095 auto &MAs = IAClass.InvariantAccesses;
3096 if (!MAs.empty()) {
3097 auto *LastMA = MAs.front();
3098
3099 isl::set AR = MA->getAccessRelation().range();
3100 isl::set LastAR = LastMA->getAccessRelation().range();
3101 bool SameAR = AR.is_equal(LastAR);
3102
3103 if (!SameAR)
3104 continue;
3105 }
3106
3107 // Add MA to the list of accesses that are in this class.
3108 MAs.push_front(MA);
3109
3110 Consolidated = true;
3111
3112 // Unify the execution context of the class and this statement.
3113 isl::set IAClassDomainCtx = IAClass.ExecutionContext;
3114 if (!IAClassDomainCtx.is_null())
3115 IAClassDomainCtx = IAClassDomainCtx.unite(MACtx).coalesce();
3116 else
3117 IAClassDomainCtx = MACtx;
3118 IAClass.ExecutionContext = IAClassDomainCtx;
3119 break;
3120 }
3121
3122 if (Consolidated)
3123 continue;
3124
3125 MACtx = MACtx.coalesce();
3126
3127 // If we did not consolidate MA, thus did not find an equivalence class
3128 // for it, we create a new one.
3129 scop->addInvariantEquivClass(
3130 InvariantEquivClassTy{PointerSCEV, MemoryAccessList{MA}, MACtx, Ty});
3131 }
3132}
3133
3134/// Find the canonical scop array info object for a set of invariant load
3135/// hoisted loads. The canonical array is the one that corresponds to the
3136/// first load in the list of accesses which is used as base pointer of a
3137/// scop array.
3139 MemoryAccessList &Accesses) {
3140 for (MemoryAccess *Access : Accesses) {
3141 const ScopArrayInfo *CanonicalArray = S.getScopArrayInfoOrNull(
3142 Access->getAccessInstruction(), MemoryKind::Array);
3143 if (CanonicalArray)
3144 return CanonicalArray;
3145 }
3146 return nullptr;
3147}
3148
3149/// Check if @p Array severs as base array in an invariant load.
3151 for (InvariantEquivClassTy &EqClass2 : S.getInvariantAccesses())
3152 for (MemoryAccess *Access2 : EqClass2.InvariantAccesses)
3153 if (Access2->getScopArrayInfo() == Array)
3154 return true;
3155 return false;
3156}
3157
3158/// Replace the base pointer arrays in all memory accesses referencing @p Old,
3159/// with a reference to @p New.
3160static void replaceBasePtrArrays(Scop &S, const ScopArrayInfo *Old,
3161 const ScopArrayInfo *New) {
3162 for (ScopStmt &Stmt : S)
3163 for (MemoryAccess *Access : Stmt) {
3164 if (Access->getLatestScopArrayInfo() != Old)
3165 continue;
3166
3167 isl::id Id = New->getBasePtrId();
3168 isl::map Map = Access->getAccessRelation();
3169 Map = Map.set_tuple_id(isl::dim::out, Id);
3170 Access->setAccessRelation(Map);
3171 }
3172}
3173
3175 for (InvariantEquivClassTy &EqClass : scop->InvariantEquivClasses) {
3176 MemoryAccessList &BasePtrAccesses = EqClass.InvariantAccesses;
3177
3178 const ScopArrayInfo *CanonicalBasePtrSAI =
3179 findCanonicalArray(*scop, BasePtrAccesses);
3180
3181 if (!CanonicalBasePtrSAI)
3182 continue;
3183
3184 for (MemoryAccess *BasePtrAccess : BasePtrAccesses) {
3185 const ScopArrayInfo *BasePtrSAI = scop->getScopArrayInfoOrNull(
3186 BasePtrAccess->getAccessInstruction(), MemoryKind::Array);
3187 if (!BasePtrSAI || BasePtrSAI == CanonicalBasePtrSAI ||
3188 !BasePtrSAI->isCompatibleWith(CanonicalBasePtrSAI))
3189 continue;
3190
3191 // we currently do not canonicalize arrays where some accesses are
3192 // hoisted as invariant loads. If we would, we need to update the access
3193 // function of the invariant loads as well. However, as this is not a
3194 // very common situation, we leave this for now to avoid further
3195 // complexity increases.
3196 if (isUsedForIndirectHoistedLoad(*scop, BasePtrSAI))
3197 continue;
3198
3199 replaceBasePtrArrays(*scop, BasePtrSAI, CanonicalBasePtrSAI);
3200 }
3201 }
3202}
3203
3205 for (MemoryAccess *Access : Stmt.MemAccs) {
3206 Type *ElementType = Access->getElementType();
3207
3208 MemoryKind Ty;
3209 if (Access->isPHIKind())
3210 Ty = MemoryKind::PHI;
3211 else if (Access->isExitPHIKind())
3213 else if (Access->isValueKind())
3214 Ty = MemoryKind::Value;
3215 else
3216 Ty = MemoryKind::Array;
3217
3218 // Create isl::pw_aff for SCEVs which describe sizes. Collect all
3219 // assumptions which are taken. isl::pw_aff objects are cached internally
3220 // and they are used later by scop.
3221 for (const SCEV *Size : Access->Sizes) {
3222 if (!Size)
3223 continue;
3224 scop->getPwAff(Size, nullptr, false, &RecordedAssumptions);
3225 }
3226 auto *SAI = scop->getOrCreateScopArrayInfo(Access->getOriginalBaseAddr(),
3227 ElementType, Access->Sizes, Ty);
3228
3229 // Create isl::pw_aff for SCEVs which describe subscripts. Collect all
3230 // assumptions which are taken. isl::pw_aff objects are cached internally
3231 // and they are used later by scop.
3232 for (const SCEV *Subscript : Access->subscripts()) {
3233 if (!Access->isAffine() || !Subscript)
3234 continue;
3235 scop->getPwAff(Subscript, Stmt.getEntryBlock(), false,
3237 }
3238 Access->buildAccessRelation(SAI);
3239 scop->addAccessData(Access);
3240 }
3241}
3242
3243/// Add the minimal/maximal access in @p Set to @p User.
3244///
3245/// @return True if more accesses should be added, false if we reached the
3246/// maximal number of run-time checks to be generated.
3248 Scop::MinMaxVectorTy &MinMaxAccesses, Scop &S) {
3249 isl::pw_multi_aff MinPMA, MaxPMA;
3250 isl::pw_aff LastDimAff;
3251 isl::aff OneAff;
3252 unsigned Pos;
3253
3254 Set = Set.remove_divs();
3255 polly::simplify(Set);
3256
3258 Set = Set.simple_hull();
3259
3260 // Restrict the number of parameters involved in the access as the lexmin/
3261 // lexmax computation will take too long if this number is high.
3262 //
3263 // Experiments with a simple test case using an i7 4800MQ:
3264 //
3265 // #Parameters involved | Time (in sec)
3266 // 6 | 0.01
3267 // 7 | 0.04
3268 // 8 | 0.12
3269 // 9 | 0.40
3270 // 10 | 1.54
3271 // 11 | 6.78
3272 // 12 | 30.38
3273 //
3274 if (isl_set_n_param(Set.get()) >
3275 static_cast<isl_size>(RunTimeChecksMaxParameters)) {
3276 unsigned InvolvedParams = 0;
3277 for (unsigned u = 0, e = isl_set_n_param(Set.get()); u < e; u++)
3278 if (Set.involves_dims(isl::dim::param, u, 1))
3279 InvolvedParams++;
3280
3281 if (InvolvedParams > RunTimeChecksMaxParameters)
3282 return false;
3283 }
3284
3285 MinPMA = Set.lexmin_pw_multi_aff();
3286 MaxPMA = Set.lexmax_pw_multi_aff();
3287
3288 MinPMA = MinPMA.coalesce();
3289 MaxPMA = MaxPMA.coalesce();
3290
3291 if (MaxPMA.is_null())
3292 return false;
3293
3294 unsigned MaxOutputSize = unsignedFromIslSize(MaxPMA.dim(isl::dim::out));
3295
3296 // Adjust the last dimension of the maximal access by one as we want to
3297 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer
3298 // we test during code generation might now point after the end of the
3299 // allocated array but we will never dereference it anyway.
3300 assert(MaxOutputSize >= 1 && "Assumed at least one output dimension");
3301
3302 Pos = MaxOutputSize - 1;
3303 LastDimAff = MaxPMA.at(Pos);
3304 OneAff = isl::aff(isl::local_space(LastDimAff.get_domain_space()));
3305 OneAff = OneAff.add_constant_si(1);
3306 LastDimAff = LastDimAff.add(OneAff);
3307 MaxPMA = MaxPMA.set_pw_aff(Pos, LastDimAff);
3308
3309 if (MinPMA.is_null() || MaxPMA.is_null())
3310 return false;
3311
3312 MinMaxAccesses.push_back(std::make_pair(MinPMA, MaxPMA));
3313
3314 return true;
3315}
3316
3317/// Wrapper function to calculate minimal/maximal accesses to each array.
3319 Scop::MinMaxVectorTy &MinMaxAccesses) {
3320 MinMaxAccesses.reserve(AliasGroup.size());
3321
3322 isl::union_set Domains = scop->getDomains();
3323 isl::union_map Accesses = isl::union_map::empty(scop->getIslCtx());
3324
3325 for (MemoryAccess *MA : AliasGroup)
3326 Accesses = Accesses.unite(MA->getAccessRelation());
3327
3328 Accesses = Accesses.intersect_domain(Domains);
3329 isl::union_set Locations = Accesses.range();
3330
3331 bool LimitReached = false;
3332 for (isl::set Set : Locations.get_set_list()) {
3333 LimitReached |= !buildMinMaxAccess(Set, MinMaxAccesses, *scop);
3334 if (LimitReached)
3335 break;
3336 }
3337
3338 return !LimitReached;
3339}
3340
3343 Domain = Domain.project_out(isl::dim::set, 0,
3344 unsignedFromIslSize(Domain.tuple_dim()));
3345 return Domain.reset_tuple_id();
3346}
3347
3350 return true;
3351
3352 if (buildAliasGroups()) {
3353 // Aliasing assumptions do not go through addAssumption but we still want to
3354 // collect statistics so we do it here explicitly.
3355 if (scop->getAliasGroups().size())
3357 return true;
3358 }
3359
3360 // If a problem occurs while building the alias groups we need to delete
3361 // this SCoP and pretend it wasn't valid in the first place. To this end
3362 // we make the assumed context infeasible.
3363 scop->invalidate(ALIASING, DebugLoc());
3364
3365 POLLY_DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << scop->getNameStr()
3366 << " could not be created. This SCoP has been dismissed.");
3367 return false;
3368}
3369
3370std::tuple<ScopBuilder::AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>>
3372 BatchAAResults BAA(AA);
3373 AliasSetTracker AST(BAA);
3374
3375 DenseMap<Value *, MemoryAccess *> PtrToAcc;
3376 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3377 for (ScopStmt &Stmt : *scop) {
3378
3379 isl::set StmtDomain = Stmt.getDomain();
3380 bool StmtDomainEmpty = StmtDomain.is_empty();
3381
3382 // Statements with an empty domain will never be executed.
3383 if (StmtDomainEmpty)
3384 continue;
3385
3386 for (MemoryAccess *MA : Stmt) {
3387 if (MA->isScalarKind())
3388 continue;
3389 if (!MA->isRead())
3390 HasWriteAccess.insert(MA->getScopArrayInfo());
3391 MemAccInst Acc(MA->getAccessInstruction());
3392 if (MA->isRead() && isa<MemTransferInst>(Acc))
3393 PtrToAcc[cast<MemTransferInst>(Acc)->getRawSource()] = MA;
3394 else
3395 PtrToAcc[Acc.getPointerOperand()] = MA;
3396 AST.add(Acc);
3397 }
3398 }
3399
3400 AliasGroupVectorTy AliasGroups;
3401 for (AliasSet &AS : AST) {
3402 if (AS.isMustAlias() || AS.isForwardingAliasSet())
3403 continue;
3404 AliasGroupTy AG;
3405 for (const Value *Ptr : AS.getPointers())
3406 AG.push_back(PtrToAcc[const_cast<Value *>(Ptr)]);
3407 if (AG.size() < 2)
3408 continue;
3409 AliasGroups.push_back(std::move(AG));
3410 }
3411
3412 return std::make_tuple(AliasGroups, HasWriteAccess);
3413}
3414
3416 // To create sound alias checks we perform the following steps:
3417 // o) We partition each group into read only and non read only accesses.
3418 // o) For each group with more than one base pointer we then compute minimal
3419 // and maximal accesses to each array of a group in read only and non
3420 // read only partitions separately.
3421 AliasGroupVectorTy AliasGroups;
3422 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3423
3424 std::tie(AliasGroups, HasWriteAccess) = buildAliasGroupsForAccesses();
3425
3426 splitAliasGroupsByDomain(AliasGroups);
3427
3428 for (AliasGroupTy &AG : AliasGroups) {
3429 if (!scop->hasFeasibleRuntimeContext())
3430 return false;
3431
3432 {
3433 IslMaxOperationsGuard MaxOpGuard(scop->getIslCtx().get(), OptComputeOut);
3434 bool Valid = buildAliasGroup(AG, HasWriteAccess);
3435 if (!Valid)
3436 return false;
3437 }
3438 if (isl_ctx_last_error(scop->getIslCtx().get()) == isl_error_quota) {
3439 scop->invalidate(COMPLEXITY, DebugLoc());
3440 return false;
3441 }
3442 }
3443
3444 return true;
3445}
3446
3448 AliasGroupTy &AliasGroup, DenseSet<const ScopArrayInfo *> HasWriteAccess) {
3449 AliasGroupTy ReadOnlyAccesses;
3450 AliasGroupTy ReadWriteAccesses;
3451 SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays;
3452 SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays;
3453
3454 if (AliasGroup.size() < 2)
3455 return true;
3456
3457 for (MemoryAccess *Access : AliasGroup) {
3458 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "PossibleAlias",
3459 Access->getAccessInstruction())
3460 << "Possibly aliasing pointer, use restrict keyword.");
3461 const ScopArrayInfo *Array = Access->getScopArrayInfo();
3462 if (HasWriteAccess.count(Array)) {
3463 ReadWriteArrays.insert(Array);
3464 ReadWriteAccesses.push_back(Access);
3465 } else {
3466 ReadOnlyArrays.insert(Array);
3467 ReadOnlyAccesses.push_back(Access);
3468 }
3469 }
3470
3471 // If there are no read-only pointers, and less than two read-write pointers,
3472 // no alias check is needed.
3473 if (ReadOnlyAccesses.empty() && ReadWriteArrays.size() <= 1)
3474 return true;
3475
3476 // If there is no read-write pointer, no alias check is needed.
3477 if (ReadWriteArrays.empty())
3478 return true;
3479
3480 // For non-affine accesses, no alias check can be generated as we cannot
3481 // compute a sufficiently tight lower and upper bound: bail out.
3482 for (MemoryAccess *MA : AliasGroup) {
3483 if (!MA->isAffine()) {
3484 scop->invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc(),
3485 MA->getAccessInstruction()->getParent());
3486 return false;
3487 }
3488 }
3489
3490 // Ensure that for all memory accesses for which we generate alias checks,
3491 // their base pointers are available.
3492 for (MemoryAccess *MA : AliasGroup) {
3493 if (MemoryAccess *BasePtrMA = scop->lookupBasePtrAccess(MA))
3494 scop->addRequiredInvariantLoad(
3495 cast<LoadInst>(BasePtrMA->getAccessInstruction()));
3496 }
3497
3498 // scop->getAliasGroups().emplace_back();
3499 // Scop::MinMaxVectorPairTy &pair = scop->getAliasGroups().back();
3500 Scop::MinMaxVectorTy MinMaxAccessesReadWrite;
3501 Scop::MinMaxVectorTy MinMaxAccessesReadOnly;
3502
3503 bool Valid;
3504
3505 Valid = calculateMinMaxAccess(ReadWriteAccesses, MinMaxAccessesReadWrite);
3506
3507 if (!Valid)
3508 return false;
3509
3510 // Bail out if the number of values we need to compare is too large.
3511 // This is important as the number of comparisons grows quadratically with
3512 // the number of values we need to compare.
3513 if (MinMaxAccessesReadWrite.size() + ReadOnlyArrays.size() >
3515 return false;
3516
3517 Valid = calculateMinMaxAccess(ReadOnlyAccesses, MinMaxAccessesReadOnly);
3518
3519 scop->addAliasGroup(MinMaxAccessesReadWrite, MinMaxAccessesReadOnly);
3520 if (!Valid)
3521 return false;
3522
3523 return true;
3524}
3525
3527 for (unsigned u = 0; u < AliasGroups.size(); u++) {
3528 AliasGroupTy NewAG;
3529 AliasGroupTy &AG = AliasGroups[u];
3530 AliasGroupTy::iterator AGI = AG.begin();
3531 isl::set AGDomain = getAccessDomain(*AGI);
3532 while (AGI != AG.end()) {
3533 MemoryAccess *MA = *AGI;
3534 isl::set MADomain = getAccessDomain(MA);
3535 if (AGDomain.is_disjoint(MADomain)) {
3536 NewAG.push_back(MA);
3537 AGI = AG.erase(AGI);
3538 } else {
3539 AGDomain = AGDomain.unite(MADomain);
3540 AGI++;
3541 }
3542 }
3543 if (NewAG.size() > 1)
3544 AliasGroups.push_back(std::move(NewAG));
3545 }
3546}
3547
3548#ifndef NDEBUG
3549static void verifyUse(Scop *S, Use &Op, LoopInfo &LI) {
3550 auto PhysUse = VirtualUse::create(S, Op, &LI, false);
3551 auto VirtUse = VirtualUse::create(S, Op, &LI, true);
3552 assert(PhysUse.getKind() == VirtUse.getKind());
3553}
3554
3555/// Check the consistency of every statement's MemoryAccesses.
3556///
3557/// The check is carried out by expecting the "physical" kind of use (derived
3558/// from the BasicBlocks instructions resides in) to be same as the "virtual"
3559/// kind of use (derived from a statement's MemoryAccess).
3560///
3561/// The "physical" uses are taken by ensureValueRead to determine whether to
3562/// create MemoryAccesses. When done, the kind of scalar access should be the
3563/// same no matter which way it was derived.
3564///
3565/// The MemoryAccesses might be changed by later SCoP-modifying passes and hence
3566/// can intentionally influence on the kind of uses (not corresponding to the
3567/// "physical" anymore, hence called "virtual"). The CodeGenerator therefore has
3568/// to pick up the virtual uses. But here in the code generator, this has not
3569/// happened yet, such that virtual and physical uses are equivalent.
3570static void verifyUses(Scop *S, LoopInfo &LI, DominatorTree &DT) {
3571 for (auto *BB : S->getRegion().blocks()) {
3572 for (auto &Inst : *BB) {
3573 auto *Stmt = S->getStmtFor(&Inst);
3574 if (!Stmt)
3575 continue;
3576
3577 if (isIgnoredIntrinsic(&Inst))
3578 continue;
3579
3580 // Branch conditions are encoded in the statement domains.
3581 if (Inst.isTerminator() && Stmt->isBlockStmt())
3582 continue;
3583
3584 // Verify all uses.
3585 for (auto &Op : Inst.operands())
3586 verifyUse(S, Op, LI);
3587
3588 // Stores do not produce values used by other statements.
3589 if (isa<StoreInst>(Inst))
3590 continue;
3591
3592 // For every value defined in the block, also check that a use of that
3593 // value in the same statement would not be an inter-statement use. It can
3594 // still be synthesizable or load-hoisted, but these kind of instructions
3595 // are not directly copied in code-generation.
3596 auto VirtDef =
3597 VirtualUse::create(S, Stmt, Stmt->getSurroundingLoop(), &Inst, true);
3598 assert(VirtDef.getKind() == VirtualUse::Synthesizable ||
3599 VirtDef.getKind() == VirtualUse::Intra ||
3600 VirtDef.getKind() == VirtualUse::Hoisted);
3601 }
3602 }
3603
3604 if (S->hasSingleExitEdge())
3605 return;
3606
3607 // PHINodes in the SCoP region's exit block are also uses to be checked.
3608 if (!S->getRegion().isTopLevelRegion()) {
3609 for (auto &Inst : *S->getRegion().getExit()) {
3610 if (!isa<PHINode>(Inst))
3611 break;
3612
3613 for (auto &Op : Inst.operands())
3614 verifyUse(S, Op, LI);
3615 }
3616 }
3617}
3618#endif
3619
3620void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) {
3621 scop.reset(new Scop(R, SE, LI, DT, *SD.getDetectionContext(&R), ORE,
3622 SD.getNextID()));
3623
3624 buildStmts(R);
3625
3626 // Create all invariant load instructions first. These are categorized as
3627 // 'synthesizable', therefore are not part of any ScopStmt but need to be
3628 // created somewhere.
3629 const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
3630 for (BasicBlock *BB : scop->getRegion().blocks()) {
3631 if (SD.isErrorBlock(*BB, scop->getRegion()))
3632 continue;
3633
3634 for (Instruction &Inst : *BB) {
3635 LoadInst *Load = dyn_cast<LoadInst>(&Inst);
3636 if (!Load)
3637 continue;
3638
3639 if (!RIL.count(Load))
3640 continue;
3641
3642 // Invariant loads require a MemoryAccess to be created in some statement.
3643 // It is not important to which statement the MemoryAccess is added
3644 // because it will later be removed from the ScopStmt again. We chose the
3645 // first statement of the basic block the LoadInst is in.
3646 ArrayRef<ScopStmt *> List = scop->getStmtListFor(BB);
3647 assert(!List.empty());
3648 ScopStmt *RILStmt = List.front();
3649 buildMemoryAccess(Load, RILStmt);
3650 }
3651 }
3653
3654 // In case the region does not have an exiting block we will later (during
3655 // code generation) split the exit block. This will move potential PHI nodes
3656 // from the current exit block into the new region exiting block. Hence, PHI
3657 // nodes that are at this point not part of the region will be.
3658 // To handle these PHI nodes later we will now model their operands as scalar
3659 // accesses. Note that we do not model anything in the exit block if we have
3660 // an exiting block in the region, as there will not be any splitting later.
3661 if (!R.isTopLevelRegion() && !scop->hasSingleExitEdge()) {
3662 for (Instruction &Inst : *R.getExit()) {
3663 PHINode *PHI = dyn_cast<PHINode>(&Inst);
3664 if (!PHI)
3665 break;
3666
3667 buildPHIAccesses(nullptr, PHI, nullptr, true);
3668 }
3669 }
3670
3671 // Create memory accesses for global reads since all arrays are now known.
3672 const SCEV *AF = SE.getConstant(IntegerType::getInt64Ty(SE.getContext()), 0);
3673 for (auto GlobalReadPair : GlobalReads) {
3674 ScopStmt *GlobalReadStmt = GlobalReadPair.first;
3675 Instruction *GlobalRead = GlobalReadPair.second;
3676 for (auto *BP : ArrayBasePointers)
3677 addArrayAccess(GlobalReadStmt, MemAccInst(GlobalRead), MemoryAccess::READ,
3678 BP, BP->getType(), false, {AF}, {nullptr}, GlobalRead);
3679 }
3680
3682
3683 /// A map from basic blocks to their invalid domains.
3684 DenseMap<BasicBlock *, isl::set> InvalidDomainMap;
3685
3686 if (!buildDomains(&R, InvalidDomainMap)) {
3688 dbgs() << "Bailing-out because buildDomains encountered problems\n");
3689 return;
3690 }
3691
3692 addUserAssumptions(AC, InvalidDomainMap);
3693
3694 // Initialize the invalid domain.
3695 for (ScopStmt &Stmt : scop->Stmts)
3696 if (Stmt.isBlockStmt())
3697 Stmt.setInvalidDomain(InvalidDomainMap[Stmt.getEntryBlock()]);
3698 else
3699 Stmt.setInvalidDomain(InvalidDomainMap[getRegionNodeBasicBlock(
3700 Stmt.getRegion()->getNode())]);
3701
3702 // Remove empty statements.
3703 // Exit early in case there are no executable statements left in this scop.
3704 scop->removeStmtNotInDomainMap();
3705 scop->simplifySCoP(false);
3706 if (scop->isEmpty()) {
3707 POLLY_DEBUG(dbgs() << "Bailing-out because SCoP is empty\n");
3708 return;
3709 }
3710
3711 // The ScopStmts now have enough information to initialize themselves.
3712 for (ScopStmt &Stmt : *scop) {
3714
3715 buildDomain(Stmt);
3717
3718 if (DetectReductions)
3719 checkForReductions(Stmt);
3720 }
3721
3722 // Check early for a feasible runtime context.
3723 if (!scop->hasFeasibleRuntimeContext()) {
3725 dbgs() << "Bailing-out because of unfeasible context (early)\n");
3726 return;
3727 }
3728
3729 // Check early for profitability. Afterwards it cannot change anymore,
3730 // only the runtime context could become infeasible.
3731 if (!scop->isProfitable(UnprofitableScalarAccs)) {
3732 scop->invalidate(PROFITABLE, DebugLoc());
3734 dbgs() << "Bailing-out because SCoP is not considered profitable\n");
3735 return;
3736 }
3737
3738 buildSchedule();
3739
3741
3742 scop->realignParams();
3744
3745 // After the context was fully constructed, thus all our knowledge about
3746 // the parameters is in there, we add all recorded assumptions to the
3747 // assumed/invalid context.
3749
3750 scop->simplifyContexts();
3751 if (!buildAliasChecks()) {
3752 POLLY_DEBUG(dbgs() << "Bailing-out because could not build alias checks\n");
3753 return;
3754 }
3755
3759 scop->simplifySCoP(true);
3760
3761 // Check late for a feasible runtime context because profitability did not
3762 // change.
3763 if (!scop->hasFeasibleRuntimeContext()) {
3764 POLLY_DEBUG(dbgs() << "Bailing-out because of unfeasible context (late)\n");
3765 return;
3766 }
3767
3768#ifndef NDEBUG
3769 verifyUses(scop.get(), LI, DT);
3770#endif
3771}
3772
3773ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA,
3774 const DataLayout &DL, DominatorTree &DT, LoopInfo &LI,
3775 ScopDetection &SD, ScalarEvolution &SE,
3776 OptimizationRemarkEmitter &ORE)
3777 : AA(AA), DL(DL), DT(DT), LI(LI), SD(SD), SE(SE), ORE(ORE) {
3778 DebugLoc Beg, End;
3779 auto P = getBBPairForRegion(R);
3780 getDebugLocations(P, Beg, End);
3781
3782 std::string Msg = "SCoP begins here.";
3783 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEntry", Beg, P.first)
3784 << Msg);
3785
3786 buildScop(*R, AC);
3787
3788 POLLY_DEBUG(dbgs() << *scop);
3789
3790 if (!scop->hasFeasibleRuntimeContext()) {
3791 InfeasibleScops++;
3792 Msg = "SCoP ends here but was dismissed.";
3793 POLLY_DEBUG(dbgs() << "SCoP detected but dismissed\n");
3794 RecordedAssumptions.clear();
3795 scop.reset();
3796 } else {
3797 Msg = "SCoP ends here.";
3798 ++ScopFound;
3799 if (scop->getMaxLoopDepth() > 0)
3800 ++RichScopFound;
3801 }
3802
3803 if (R->isTopLevelRegion())
3804 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.first)
3805 << Msg);
3806 else
3807 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.second)
3808 << Msg);
3809}
static cl::opt< int > OptComputeOut("polly-dependences-computeout", cl::desc("Bound the dependence analysis by a maximal amount of " "computational steps (0 means no bound)"), cl::Hidden, cl::init(500000), cl::cat(PollyCategory))
#define DEBUG_TYPE
unsigned unsignedFromIslSize(const isl::size &Size)
Check that Size is valid (only on debug builds) and cast it to unsigned.
Definition ISLTools.h:40
llvm::cl::OptionCategory PollyCategory
#define POLLY_DEBUG(X)
Definition PollyDebug.h:23
static cl::opt< int > OptComputeOut("polly-analysis-computeout", cl::desc("Bound the scop analysis by a maximal amount of " "computational steps (0 means no bound)"), cl::Hidden, cl::init(800000), cl::cat(PollyCategory))
static cl::opt< bool > DisableMultiplicativeReductions("polly-disable-multiplicative-reductions", cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::cat(PollyCategory))
static void replaceBasePtrArrays(Scop &S, const ScopArrayInfo *Old, const ScopArrayInfo *New)
Replace the base pointer arrays in all memory accesses referencing Old, with a reference to New.
static std::pair< isl::set, isl::set > partitionSetParts(isl::set S, unsigned Dim)
Compute the (un)bounded parts of S wrt.
static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim)
}
static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L, isl::pw_aff R)
Create the conditions under which L Pred R is true.
static const ScopArrayInfo * findCanonicalArray(Scop &S, MemoryAccessList &Accesses)
Find the canonical scop array info object for a set of invariant load hoisted loads.
static isl::set collectBoundedParts(isl::set S)
Add BSet to set BoundedParts if BSet is bounded.
static void joinOrderedPHIs(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
If the BasicBlock has an edge from itself, ensure that the PHI WRITEs for the incoming values from th...
static cl::opt< std::string > UserContextStr("polly-context", cl::value_desc("isl parameter set"), cl::desc("Provide additional constraints on the context parameters"), cl::init(""), cl::cat(PollyCategory))
static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE)
Check if Expr is divisible by Size.
static BasicBlock * getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx)
Return the idx'th block that is executed after RN.
static cl::opt< bool > PollyAllowDereferenceOfAllFunctionParams("polly-allow-dereference-of-all-function-parameters", cl::desc("Treat all parameters to functions that are pointers as dereferencible." " This is useful for invariant load hoisting, since we can generate" " less runtime checks. This is only valid if all pointers to functions" " are always initialized, so that Polly can choose to hoist" " their loads. "), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
static isl::set getAccessDomain(MemoryAccess *MA)
static cl::opt< unsigned > RunTimeChecksMaxArraysPerGroup("polly-rtc-max-arrays-per-group", cl::desc("The maximal number of arrays to compare in each alias group."), cl::Hidden, cl::init(20), cl::cat(PollyCategory))
static bool isAccessRangeTooComplex(isl::set AccessRange)
Check if an access range is too complex.
static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp)
Return the reduction type for a given binary operator.
static bool isUsedForIndirectHoistedLoad(Scop &S, const ScopArrayInfo *Array)
Check if Array severs as base array in an invariant load.
static cl::opt< bool, true > XModelReadOnlyScalars("polly-analyze-read-only-scalars", cl::desc("Model read-only scalar values in the scop description"), cl::location(ModelReadOnlyScalars), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static bool isAParameter(llvm::Value *maybeParam, const Function &F)
static isl::schedule combineInSequence(isl::schedule Prev, isl::schedule Succ)
static void joinOrderedInstructions(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
Ensure that the order of ordered instructions does not change.
static cl::opt< unsigned > RunTimeChecksMaxAccessDisjuncts("polly-rtc-max-array-disjuncts", cl::desc("The maximal number of disjunts allowed in memory accesses to " "to build RTCs."), cl::Hidden, cl::init(8), cl::cat(PollyCategory))
GranularityChoice
static void joinOperandTree(EquivalenceClasses< Instruction * > &UnionFind, ArrayRef< Instruction * > ModeledInsts)
Join instructions to the same statement if one uses the scalar result of the other.
bool hasIntersectingAccesses(isl::set AllAccs, MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set Domain, SmallVector< MemoryAccess *, 8 > &MemAccs)
True if AllAccs intersects with MemAccs except LoadMA and StoreMA.
static cl::opt< bool > DetectReductions("polly-detect-reductions", cl::desc("Detect and exploit reductions"), cl::Hidden, cl::init(true), cl::cat(PollyCategory))
static std::string makeStmtName(BasicBlock *BB, long BBIdx, int Count, bool IsMain, bool IsLast=false)
Generate a name for a statement.
static BasicBlock * getRegionNodeBasicBlock(RegionNode *RN)
Helper to treat non-affine regions and basic blocks the same.
static cl::opt< GranularityChoice > StmtGranularity("polly-stmt-granularity", cl::desc("Algorithm to use for splitting basic blocks into multiple statements"), cl::values(clEnumValN(GranularityChoice::BasicBlocks, "bb", "One statement per basic block"), clEnumValN(GranularityChoice::ScalarIndependence, "scalar-indep", "Scalar independence heuristic"), clEnumValN(GranularityChoice::Stores, "store", "Store-level granularity")), cl::init(GranularityChoice::ScalarIndependence), cl::cat(PollyCategory))
static bool containsErrorBlock(RegionNode *RN, const Region &R, ScopDetection *SD)
static void verifyUse(Scop *S, Use &Op, LoopInfo &LI)
STATISTIC(ScopFound, "Number of valid Scops")
static unsigned const MaxDimensionsInAccessRange
static bool buildMinMaxAccess(isl::set Set, Scop::MinMaxVectorTy &MinMaxAccesses, Scop &S)
Add the minimal/maximal access in Set to User.
static isl::multi_union_pw_aff mapToDimension(isl::union_set USet, unsigned N)
static void verifyUses(Scop *S, LoopInfo &LI, DominatorTree &DT)
Check the consistency of every statement's MemoryAccesses.
static MemoryAccess::ReductionType combineReductionType(MemoryAccess::ReductionType RT0, MemoryAccess::ReductionType RT1)
Combine two reduction types.
static bool isOrderedInstruction(Instruction *Inst)
Is Inst an ordered instruction?
static cl::opt< unsigned > RunTimeChecksMaxParameters("polly-rtc-max-parameters", cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden, cl::init(8), cl::cat(PollyCategory))
static cl::opt< bool > UnprofitableScalarAccs("polly-unprofitable-scalar-accs", cl::desc("Count statements with scalar accesses as not optimizable"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
bool checkCandidatePairAccesses(MemoryAccess *LoadMA, MemoryAccess *StoreMA, isl::set Domain, SmallVector< MemoryAccess *, 8 > &MemAccs)
Test if the accesses of LoadMA and StoreMA can form a reduction.
static cl::opt< bool > PollyIgnoreInbounds("polly-ignore-inbounds", cl::desc("Do not take inbounds assumptions at all"), cl::Hidden, cl::init(false), cl::cat(PollyCategory))
__isl_null isl_pw_aff * isl_pw_aff_free(__isl_take isl_pw_aff *pwaff)
__isl_give isl_pw_aff * isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls)
Definition isl_aff.c:206
__isl_give isl_space * isl_pw_aff_get_domain_space(__isl_keep isl_pw_aff *pwaff)
__isl_export __isl_give isl_set * isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2)
Definition isl_aff.c:3069
__isl_export __isl_give isl_set * isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2)
Definition isl_aff.c:3063
__isl_give isl_pw_aff * isl_pw_aff_copy(__isl_keep isl_pw_aff *pwaff)
isl::val get_denominator_val() const
isl::aff add_constant_si(int v) const
isl::aff get_div(int pos) const
boolean is_equal(const isl::basic_set &bset2) const
class size dim(isl::dim type) const
isl::basic_set fix_si(isl::dim type, unsigned int pos, int value) const
static isl::constraint alloc_inequality(isl::local_space ls)
static isl::constraint alloc_equality(isl::local_space ls)
bool is_null() const
static isl::id alloc(isl::ctx ctx, const std::string &name, void *user)
isl::map add_constraint(isl::constraint constraint) const
isl::map equate(isl::dim type1, int pos1, isl::dim type2, int pos2) const
static isl::map universe(isl::space space)
class size domain_tuple_dim() const
isl::map set_tuple_id(isl::dim type, isl::id id) const
isl::set range() const
isl::map unite(isl::map map2) const
isl::space get_space() const
isl::set domain() const
boolean is_empty() const
boolean has_equal_space(const isl::map &map2) const
isl::map intersect_domain(isl::set set) const
static isl::map lex_le(isl::space set_space)
__isl_give isl_map * copy() const &
boolean involves_dims(isl::dim type, unsigned int first, unsigned int n) const
isl::set lt_set(isl::pw_aff pwaff2) const
isl::set le_set(isl::pw_aff pwaff2) const
isl::space get_domain_space() const
isl::set eq_set(isl::pw_aff pwaff2) const
isl::set ne_set(isl::pw_aff pwaff2) const
isl::set ge_set(isl::pw_aff pwaff2) const
isl::multi_pw_aff add(const isl::multi_pw_aff &multi2) const
isl::set gt_set(isl::pw_aff pwaff2) const
isl::pw_aff at(int pos) const
class size dim(isl::dim type) const
isl::multi_pw_aff set_pw_aff(int pos, const isl::pw_aff &el) const
isl::pw_multi_aff coalesce() const
static isl::pw_multi_aff project_out_map(isl::space space, isl::dim type, unsigned int first, unsigned int n)
isl::schedule_node insert_mark(isl::id mark) const
isl::schedule_node child(int pos) const
isl::schedule get_schedule() const
bool is_null() const
isl::schedule insert_partial_schedule(isl::multi_union_pw_aff partial) const
isl::schedule_node get_root() const
static isl::schedule from_domain(isl::union_set domain)
isl::union_set get_domain() const
isl::schedule sequence(isl::schedule schedule2) const
isl::set project_out(isl::dim type, unsigned int first, unsigned int n) const
isl::set intersect(isl::set set2) const
isl::set subtract(isl::set set2) const
boolean involves_dims(isl::dim type, unsigned int first, unsigned int n) const
isl::set set_dim_id(isl::dim type, unsigned int pos, isl::id id) const
isl::set insert_dims(isl::dim type, unsigned int pos, unsigned int n) const
int find_dim_by_id(isl::dim type, const isl::id &id) const
static isl::set universe(isl::space space)
class size n_basic_set() const
__isl_give isl_set * copy() const &
isl::set complement() const
isl::set gist_params(isl::set context) const
isl::pw_multi_aff lexmax_pw_multi_aff() const
boolean is_subset(const isl::set &set2) const
isl::set remove_dims(isl::dim type, unsigned int first, unsigned int n) const
isl::pw_multi_aff lexmin_pw_multi_aff() const
isl::set detect_equalities() const
std::string get_dim_name(isl::dim type, unsigned int pos) const
isl::set set_tuple_id(isl::id id) const
isl::set coalesce() const
bool is_null() const
static isl::set empty(isl::space space)
class size tuple_dim() const
isl::set add_constraint(isl::constraint constraint) const
isl::space get_space() const
isl::set apply(isl::map map) const
boolean is_empty() const
__isl_give isl_set * release()
isl::set lower_bound_si(isl::dim type, unsigned int pos, int value) const
__isl_keep isl_set * get() const
class size dim(isl::dim type) const
isl::set add_dims(isl::dim type, unsigned int n) const
isl::set eliminate(isl::dim type, unsigned int first, unsigned int n) const
boolean is_disjoint(const isl::set &set2) const
isl::set unite(isl::set set2) const
isl::basic_set_list get_basic_set_list() const
boolean is_equal(const isl::set &set2) const
isl::basic_set simple_hull() const
isl::set remove_divs() const
isl::basic_set affine_hull() const
isl::set params() const
isl::set project_out_all_params() const
class size dim(isl::dim type) const
isl::id get_dim_id(isl::dim type, unsigned int pos) const
isl::space map_from_set() const
isl::space range() const
isl::space align_params(isl::space space2) const
isl::union_set range() const
isl::union_map unite(isl::union_map umap2) const
isl::union_map intersect_range(isl::space space) const
static isl::union_map empty(isl::ctx ctx)
isl::set params() const
isl::union_map intersect_domain(isl::space space) const
static isl::union_pw_multi_aff empty(isl::space space)
boolean contains(const isl::space &space) const
isl::set_list get_set_list() const
isl::set extract_set(isl::space space) const
isl::space get_space() const
boolean is_empty() const
boolean is_int() const
Scoped limit of ISL operations.
Definition GICHelper.h:424
Utility proxy to wrap the common members of LoadInst and StoreInst.
Definition ScopHelper.h:140
llvm::Value * getValueOperand() const
Definition ScopHelper.h:237
bool isLoad() const
Definition ScopHelper.h:310
static MemAccInst dyn_cast(llvm::Value &V)
Definition ScopHelper.h:178
bool isStore() const
Definition ScopHelper.h:311
llvm::Value * getPointerOperand() const
Definition ScopHelper.h:248
Represent memory accesses in statements.
Definition ScopInfo.h:426
void addIncoming(BasicBlock *IncomingBlock, Value *IncomingValue)
Add a new incoming block/value pairs for this PHI/ExitPHI access.
Definition ScopInfo.h:731
void dump() const
Print the MemoryAccess to stderr.
Definition ScopInfo.cpp:952
SmallVector< const SCEV *, 4 > Sizes
Size of each dimension of the accessed array.
Definition ScopInfo.h:543
AccessType
The access type of a memory access.
Definition ScopInfo.h:452
ReductionType
Reduction access type.
Definition ScopInfo.h:461
@ RT_BOTTOM
Pseudo type for the data flow analysis.
Definition ScopInfo.h:469
@ RT_BOR
Bitwise Or.
Definition ScopInfo.h:465
@ RT_BAND
Bitwise And.
Definition ScopInfo.h:467
@ RT_ADD
Addition.
Definition ScopInfo.h:463
@ RT_BXOR
Bitwise XOr.
Definition ScopInfo.h:466
@ RT_NONE
Indicate no reduction at all.
Definition ScopInfo.h:462
@ RT_MUL
Multiplication.
Definition ScopInfo.h:464
bool isValueKind() const
Old name of isOriginalValueKind().
Definition ScopInfo.h:981
bool isPHIKind() const
Old name of isOriginalPHIKind.
Definition ScopInfo.h:993
bool isWrite() const
Is this a write memory access?
Definition ScopInfo.h:764
Instruction * getAccessInstruction() const
Return the access instruction of this memory access.
Definition ScopInfo.h:880
iterator_range< SubscriptsTy::const_iterator > subscripts() const
Return an iterator range containing the subscripts.
Definition ScopInfo.h:883
bool isExitPHIKind() const
Old name of isOriginalExitPHIKind().
Definition ScopInfo.h:1009
bool isRead() const
Is this a read memory access?
Definition ScopInfo.h:755
void buildAccessRelation(const ScopArrayInfo *SAI)
Assemble the access relation from all available information.
Definition ScopInfo.cpp:814
bool isScalarKind() const
Old name of isOriginalScalarKind.
Definition ScopInfo.h:968
Type * getElementType() const
Return the element type of the accessed array wrt. this access.
Definition ScopInfo.h:859
const ScopArrayInfo * getScopArrayInfo() const
Legacy name of getOriginalScopArrayInfo().
Definition ScopInfo.h:848
Value * getOriginalBaseAddr() const
Get the original base address of this access (e.g.
Definition ScopInfo.h:828
ScopStmt * getStatement() const
Get the statement that contains this memory access.
Definition ScopInfo.h:1026
bool isAffine() const
Is the memory access affine?
Definition ScopInfo.h:1080
isl::map getAccessRelation() const
Old name of getLatestAccessRelation().
Definition ScopInfo.h:790
bool isMemoryIntrinsic() const
Is this a memory intrinsic access (memcpy, memset, memmove)?
Definition ScopInfo.h:767
A class to store information about arrays in the SCoP.
Definition ScopInfo.h:214
bool isCompatibleWith(const ScopArrayInfo *Array) const
Verify that Array is compatible to this ScopArrayInfo.
Definition ScopInfo.cpp:268
isl::id getBasePtrId() const
Return the isl id for the base pointer.
Definition ScopInfo.cpp:339
void buildDomain(ScopStmt &Stmt)
Build the domain of Stmt.
void propagateDomainConstraintsToRegionExit(BasicBlock *BB, Loop *BBLoop, SmallPtrSetImpl< BasicBlock * > &FinishedExitBlocks, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate domains that are known due to graph properties.
bool isRequiredInvariantLoad(LoadInst *LI) const
Return true if and only if LI is a required invariant load.
bool propagateInvalidStmtDomains(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate invalid domains of statements through R.
void ensurePHIWrite(PHINode *PHI, ScopStmt *IncomintStmt, BasicBlock *IncomingBlock, Value *IncomingValue, bool IsExitBlock)
Create a write MemoryAccess for the incoming block of a phi node.
void addInvariantLoads(ScopStmt &Stmt, InvariantAccessesTy &InvMAs)
Add invariant loads listed in InvMAs with the domain of Stmt.
void canonicalizeDynamicBasePtrs()
Canonicalize arrays with base pointers from the same equivalence class.
bool calculateMinMaxAccess(AliasGroupTy AliasGroup, Scop::MinMaxVectorTy &MinMaxAccesses)
Wrapper function to calculate minimal/maximal accesses to each array.
void verifyInvariantLoads()
Verify that all required invariant loads have been hoisted.
void addUserContext()
Add user provided parameter constraints to context (command line).
void ensureValueRead(Value *V, ScopStmt *UserStmt)
Ensure an llvm::Value is available in the BB's statement, creating a MemoryAccess for reloading it if...
struct LoopStackElement { Loop *L; isl::schedule Schedule; unsigned NumBlocksProcessed; LoopStackElement(Loop *L, isl::schedule S, unsigned NumBlocksProcessed) :L(L), Schedule(S), NumBlocksProcessed(NumBlocksProcessed) {} } LoopStackElementTy
A loop stack element to keep track of per-loop information during schedule construction.
void buildPHIAccesses(ScopStmt *PHIStmt, PHINode *PHI, Region *NonAffineSubRegion, bool IsExitBlock=false)
Create MemoryAccesses for the given PHI node in the given region.
void buildSchedule()
Construct the schedule of this SCoP.
SmallVector< std::pair< ScopStmt *, Instruction * >, 16 > GlobalReads
Set of instructions that might read any memory location.
Definition ScopBuilder.h:57
ScalarEvolution & SE
The ScalarEvolution to help building Scop.
Definition ScopBuilder.h:51
void foldAccessRelations()
Fold memory accesses to handle parametric offset.
std::tuple< AliasGroupVectorTy, DenseSet< const ScopArrayInfo * > > buildAliasGroupsForAccesses()
Build alias groups for all memory accesses in the Scop.
bool propagateDomainConstraints(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Propagate the domain constraints through the region R.
bool buildConditionSets(BasicBlock *BB, Instruction *TI, Loop *L, __isl_keep isl_set *Domain, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, SmallVectorImpl< __isl_give isl_set * > &ConditionSets)
Build the conditions sets for the terminator TI in the Domain.
void addPHIReadAccess(ScopStmt *PHIStmt, PHINode *PHI)
Create a MemoryAccess for reading the value of a phi.
bool buildAccessCallInst(MemAccInst Inst, ScopStmt *Stmt)
Try to build a MemoryAccess for a call instruction.
void buildScalarDependences(ScopStmt *UserStmt, Instruction *Inst)
Analyze and extract the cross-BB scalar dependences (or, dataflow dependencies) of an instruction.
void foldSizeConstantsToRight()
Fold size constants to the right.
SmallSetVector< Value *, 16 > ArrayBasePointers
Set of all accessed array base pointers.
Definition ScopBuilder.h:60
SmallVector< LoopStackElementTy, 4 > LoopStackTy
The loop stack used for schedule construction.
MemoryAccess * addMemoryAccess(ScopStmt *Stmt, Instruction *Inst, MemoryAccess::AccessType AccType, Value *BaseAddress, Type *ElemType, bool Affine, Value *AccessValue, ArrayRef< const SCEV * > Subscripts, ArrayRef< const SCEV * > Sizes, MemoryKind Kind)
Create a new MemoryAccess object and add it to AccFuncMap.
void hoistInvariantLoads()
Hoist invariant memory loads and check for required ones.
SmallVector< AliasGroupTy, 4 > AliasGroupVectorTy
A vector of alias groups.
AAResults & AA
The AAResults to build AliasSetTracker.
Definition ScopBuilder.h:36
bool buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt)
Try to build a multi-dimensional fixed sized MemoryAccess from the Load/Store instruction.
DominatorTree & DT
DominatorTree to reason about guaranteed execution.
Definition ScopBuilder.h:42
__isl_give isl_set * buildUnsignedConditionSets(BasicBlock *BB, Value *Condition, __isl_keep isl_set *Domain, const SCEV *SCEV_TestVal, const SCEV *SCEV_UpperBound, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, bool IsStrictUpperBound)
Build condition sets for unsigned ICmpInst(s).
const DataLayout & DL
Target data for element size computing.
Definition ScopBuilder.h:39
bool buildAccessMemIntrinsic(MemAccInst Inst, ScopStmt *Stmt)
Try to build a MemoryAccess for a memory intrinsic.
void assumeNoOutOfBounds()
Assume that all memory accesses are within bounds.
isl::set getNonHoistableCtx(MemoryAccess *Access, isl::union_map Writes)
Return the context under which the access cannot be hoisted.
void buildInvariantEquivalenceClasses()
Create equivalence classes for required invariant accesses.
bool buildAliasGroups()
Build all alias groups for this SCoP.
void addArrayAccess(ScopStmt *Stmt, MemAccInst MemAccInst, MemoryAccess::AccessType AccType, Value *BaseAddress, Type *ElemType, bool IsAffine, ArrayRef< const SCEV * > Subscripts, ArrayRef< const SCEV * > Sizes, Value *AccessValue)
Create a MemoryAccess that represents either a LoadInst or StoreInst.
isl::set adjustDomainDimensions(isl::set Dom, Loop *OldL, Loop *NewL)
Adjust the dimensions of Dom that was constructed for OldL to be compatible to domains constructed fo...
bool buildAccessMultiDimParam(MemAccInst Inst, ScopStmt *Stmt)
Try to build a multi-dimensional parametric sized MemoryAccess.
void buildEscapingDependences(Instruction *Inst)
Build the escaping dependences for Inst.
void buildEqivClassBlockStmts(BasicBlock *BB)
Create one or more ScopStmts for BB using equivalence classes.
void splitAliasGroupsByDomain(AliasGroupVectorTy &AliasGroups)
Split alias groups by iteration domains.
bool buildAliasGroup(AliasGroupTy &AliasGroup, DenseSet< const ScopArrayInfo * > HasWriteAccess)
Build a given alias group and its access data.
void addUserAssumptions(AssumptionCache &AC, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Add user provided parameter constraints to context (source code).
void checkForReductions(ScopStmt &Stmt)
Check for reductions in Stmt.
bool buildDomains(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Compute the domain for each basic block in R.
void buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore=false)
Create one or more ScopStmts for BB.
ScopDetection & SD
Valid Regions for Scop.
Definition ScopBuilder.h:48
bool shouldModelInst(Instruction *Inst, Loop *L)
Should an instruction be modeled in a ScopStmt.
std::unique_ptr< Scop > scop
Definition ScopBuilder.h:63
void buildMemoryAccess(MemAccInst Inst, ScopStmt *Stmt)
Build an instance of MemoryAccess from the Load/Store instruction.
bool buildAliasChecks()
Build the alias checks for this SCoP.
void updateAccessDimensionality()
Update access dimensionalities.
void addRecordedAssumptions()
Add all recorded assumptions to the assumed context.
void buildAccessRelations(ScopStmt &Stmt)
Build the access relation of all memory accesses of Stmt.
RecordedAssumptionsTy RecordedAssumptions
Collection to hold taken assumptions.
Definition ScopBuilder.h:75
bool hasNonHoistableBasePtrInScop(MemoryAccess *MA, isl::union_map Writes)
Check if the base ptr of MA is in the SCoP but not hoistable.
bool addLoopBoundsToHeaderDomain(Loop *L, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Add loop carried constraints to the header block of the loop L.
bool buildDomainsWithBranchConstraints(Region *R, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap)
Compute the branching constraints for each basic block in R.
void buildAccessFunctions()
Build the access functions for the subregion SR.
bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty, bool MAInvalidCtxIsEmpty, bool NonHoistableCtxIsEmpty)
Check if MA can always be hoisted without execution context.
bool buildAccessSingleDim(MemAccInst Inst, ScopStmt *Stmt)
Build a single-dimensional parametric sized MemoryAccess from the Load/Store instruction.
void collectSurroundingLoops(ScopStmt &Stmt)
Fill NestLoops with loops surrounding Stmt.
void finalizeAccesses()
Finalize all access relations.
void buildScop(Region &R, AssumptionCache &AC)
LoopInfo & LI
LoopInfo for information about loops.
Definition ScopBuilder.h:45
OptimizationRemarkEmitter & ORE
An optimization diagnostic interface to add optimization remarks.
Definition ScopBuilder.h:54
void buildStmts(Region &SR)
Create ScopStmt for all BBs and non-affine subregions of SR.
void ensureValueWrite(Instruction *Inst)
Create a MemoryAccess for writing an llvm::Instruction.
SmallVector< MemoryAccess *, 4 > AliasGroupTy
A vector of memory accesses that belong to an alias group.
__isl_give isl_pw_aff * getPwAff(BasicBlock *BB, DenseMap< BasicBlock *, isl::set > &InvalidDomainMap, const SCEV *E, bool NonNegative=false)
Compute the isl representation for the SCEV E in this BB.
isl::set getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain)
Compute the union of predecessor domains for BB.
ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA, const DataLayout &DL, DominatorTree &DT, LoopInfo &LI, ScopDetection &SD, ScalarEvolution &SE, OptimizationRemarkEmitter &ORE)
Pass to detect the maximal static control parts (Scops) of a function.
bool isErrorBlock(llvm::BasicBlock &BB, const llvm::Region &R)
Check if the block is a error block.
Statement of the Scop.
Definition ScopInfo.h:1135
MemoryAccess & getArrayAccessFor(const Instruction *Inst) const
Return the only array access for Inst.
Definition ScopInfo.h:1429
Scop * getParent()
Definition ScopInfo.h:1523
BasicBlock * getEntryBlock() const
Return a BasicBlock from this statement.
isl::set Domain
The iteration domain describes the set of iterations for which this statement is executed.
Definition ScopInfo.h:1202
const std::vector< Instruction * > & getInstructions() const
Definition ScopInfo.h:1526
bool isBlockStmt() const
Return true if this statement represents a single basic block.
Definition ScopInfo.h:1316
isl::set getInvalidContext() const
Get the invalid context for this statement.
Definition ScopInfo.h:1304
SmallVector< Loop *, 4 > NestLoops
Definition ScopInfo.h:1253
Region * getRegion() const
Get the region represented by this ScopStmt (if any).
Definition ScopInfo.h:1325
bool represents(BasicBlock *BB) const
Return whether this statement represents BB.
Definition ScopInfo.h:1346
BasicBlock * getBasicBlock() const
Get the BasicBlock represented by this ScopStmt (if any).
Definition ScopInfo.h:1313
MemoryAccessVec MemAccs
The memory accesses of this statement.
Definition ScopInfo.h:1207
const char * getBaseName() const
bool contains(const Loop *L) const
Return whether L is boxed within this statement.
Definition ScopInfo.h:1337
void addAccess(MemoryAccess *Access, bool Prepend=false)
Add Access to this statement's list of accesses.
bool isRegionStmt() const
Return true if this statement represents a whole region.
Definition ScopInfo.h:1328
void setInvalidDomain(isl::set ID)
Set the invalid context for this statement to ID.
isl::set getDomain() const
Get the iteration domain of this ScopStmt.
MemoryAccess * lookupValueWriteOf(Instruction *Inst) const
Return the MemoryAccess that writes the value of an instruction defined in this statement,...
Definition ScopInfo.h:1439
Loop * getSurroundingLoop() const
Return the closest innermost loop that contains this statement, but is not contained in it.
Definition ScopInfo.h:1376
MemoryAccess * lookupPHIWriteOf(PHINode *PHI) const
Return the PHI write MemoryAccess for the incoming values from any basic block in this ScopStmt,...
Definition ScopInfo.h:1460
MemoryAccess * lookupValueReadOf(Value *Inst) const
Return the MemoryAccess that reloads a value, or nullptr if not existing, respectively not yet added.
Definition ScopInfo.h:1447
Static Control Part.
Definition ScopInfo.h:1625
SmallVector< MinMaxAccessTy, 4 > MinMaxVectorTy
Vector of minimal/maximal accesses to different arrays.
Definition ScopInfo.h:1631
static void incrementNumberOfAliasingAssumptions(unsigned Step)
Increment actual number of aliasing assumptions taken.
const Region & getRegion() const
Get the maximum region of this static control part.
Definition ScopInfo.h:2083
static VirtualUse create(Scop *S, const Use &U, LoopInfo *LI, bool Virtual)
Get a VirtualUse for an llvm::Use.
enum isl_error isl_ctx_last_error(isl_ctx *ctx)
Definition isl_ctx.c:321
#define __isl_give
Definition ctx.h:19
@ isl_error_quota
Definition ctx.h:81
#define __isl_keep
Definition ctx.h:25
int isl_size
Definition ctx.h:96
__isl_null isl_id * isl_id_free(__isl_take isl_id *id)
Definition isl_id.c:207
void * isl_id_get_user(__isl_keep isl_id *id)
Definition isl_id.c:36
#define S(TYPE, NAME)
#define isl_set
#define C(FN,...)
Definition isl_test2.cc:197
#define assert(exp)
__isl_give isl_local_space * isl_local_space_from_space(__isl_take isl_space *space)
aff manage_copy(__isl_keep isl_aff *ptr)
boolean manage(isl_bool val)
std::forward_list< MemoryAccess * > MemoryAccessList
Ordered list type to hold accesses.
Definition ScopInfo.h:1086
std::pair< isl::pw_aff, isl::set > PWACtx
The result type of the SCEVAffinator.
llvm::Loop * getRegionNodeLoop(llvm::RegionNode *RN, llvm::LoopInfo &LI)
Return the smallest loop surrounding RN.
bool isAffineConstraint(llvm::Value *V, const llvm::Region *R, llvm::Loop *Scope, llvm::ScalarEvolution &SE, ParameterSetTy &Params, bool OrExpr=false)
Check if V describes an affine constraint in R.
unsigned const MaxDisjunctsInDomain
Definition ScopInfo.cpp:115
std::string getIslCompatibleName(const std::string &Prefix, const llvm::Value *Val, long Number, const std::string &Suffix, bool UseInstructionNames)
Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
void findValues(const llvm::SCEV *Expr, llvm::ScalarEvolution &SE, llvm::SetVector< llvm::Value * > &Values)
Find the values referenced by SCEVUnknowns in a given SCEV expression.
void findLoops(const llvm::SCEV *Expr, llvm::SetVector< const llvm::Loop * > &Loops)
Find the loops referenced from a SCEV expression.
llvm::Value * getConditionFromTerminator(llvm::Instruction *TI)
Return the condition for the terminator TI.
SmallVector< InvariantAccess, 8 > InvariantAccessesTy
Ordered container type to hold invariant accesses.
Definition ScopInfo.h:1098
llvm::SetVector< llvm::AssertingVH< llvm::LoadInst > > InvariantLoadsSetTy
Type for a set of invariant loads.
Definition ScopHelper.h:109
llvm::SetVector< const llvm::SCEV * > ParameterSetTy
Set type for parameters.
Definition ScopHelper.h:112
bool isAffineExpr(const llvm::Region *R, llvm::Loop *Scope, const llvm::SCEV *Expression, llvm::ScalarEvolution &SE, InvariantLoadsSetTy *ILS=nullptr)
unsigned getNumBlocksInRegionNode(llvm::RegionNode *RN)
Get the number of blocks in RN.
llvm::Loop * getFirstNonBoxedLoopFor(llvm::Loop *L, llvm::LoopInfo &LI, const BoxedLoopsSetTy &BoxedLoops)
void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End)
Set the begin and end source location for the region limited by P.
@ AS_RESTRICTION
Definition ScopHelper.h:57
@ AS_ASSUMPTION
Definition ScopHelper.h:57
MemoryKind
The different memory kinds used in Polly.
Definition ScopInfo.h:95
@ Array
MemoryKind::Array: Models a one or multi-dimensional array.
Definition ScopInfo.h:110
@ Value
MemoryKind::Value: Models an llvm::Value.
Definition ScopInfo.h:149
@ PHI
MemoryKind::PHI: Models PHI nodes within the SCoP.
Definition ScopInfo.h:186
@ ExitPHI
MemoryKind::ExitPHI: Models PHI nodes in the SCoP's exit block.
Definition ScopInfo.h:196
bool hasDisableAllTransformsHint(llvm::Loop *L)
Does the loop's LoopID contain a 'llvm.loop.disable_heuristics' property?
const llvm::SCEV * tryForwardThroughPHI(const llvm::SCEV *Expr, llvm::Region &R, llvm::ScalarEvolution &SE, ScopDetection *SD)
Try to look through PHI nodes, where some incoming edges come from error blocks.
bool isDebugCall(llvm::Instruction *Inst)
Is the given instruction a call to a debug function?
llvm::iota_range< unsigned > rangeIslSize(unsigned Begin, isl::size End)
Check that End is valid and return an iterator from Begin to End.
Definition ISLTools.cpp:597
void simplify(isl::set &Set)
Simplify a set inplace.
Definition ISLTools.cpp:289
BBPair getBBPairForRegion(const Region *R)
Return the region delimiters (entry & exit block) of R.
llvm::Loop * getLoopSurroundingScop(Scop &S, llvm::LoopInfo &LI)
Get the smallest loop that contains S but is not in S.
bool UseInstructionNames
Definition ScopInfo.cpp:153
void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions, AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc, AssumptionSign Sign, llvm::BasicBlock *BB=nullptr, bool RTC=true)
Record an assumption for later addition to the assumed context.
std::pair< const llvm::SCEVConstant *, const llvm::SCEV * > extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE)
Extract the constant factors from the multiplication M.
bool ModelReadOnlyScalars
Command line switch whether to model read-only accesses.
isl::id createIslLoopAttr(isl::ctx Ctx, llvm::Loop *L)
Create an isl::id that identifies an original loop.
bool PollyUseRuntimeAliasChecks
bool PollyDelinearize
@ INFINITELOOP
Definition ScopHelper.h:51
@ ERRORBLOCK
Definition ScopHelper.h:49
@ INVARIANTLOAD
Definition ScopHelper.h:52
@ COMPLEXITY
Definition ScopHelper.h:50
@ ALIASING
Definition ScopHelper.h:44
@ PROFITABLE
Definition ScopHelper.h:48
@ INBOUNDS
Definition ScopHelper.h:45
@ DELINEARIZATION
Definition ScopHelper.h:53
llvm::Value * getUniqueNonErrorValue(llvm::PHINode *PHI, llvm::Region *R, ScopDetection *SD)
Return a unique non-error block incoming value for PHI if available.
bool PollyInvariantLoadHoisting
bool isIgnoredIntrinsic(const llvm::Value *V)
Return true iff V is an intrinsic that we ignore during code generation.
bool canSynthesize(const llvm::Value *V, const Scop &S, llvm::ScalarEvolution *SE, llvm::Loop *Scope)
Check whether a value an be synthesized by the code generator.
llvm::APInt APIntFromVal(__isl_take isl_val *Val)
Translate isl_val to llvm::APInt.
Definition GICHelper.cpp:51
unsigned getNumBlocksInLoop(llvm::Loop *L)
Get the number of blocks in L.
__isl_export __isl_give isl_set * isl_set_universe(__isl_take isl_space *space)
Definition isl_map.c:6366
__isl_export __isl_give isl_set * isl_set_coalesce(__isl_take isl_set *set)
__isl_export __isl_give isl_set * isl_set_subtract(__isl_take isl_set *set1, __isl_take isl_set *set2)
__isl_export __isl_give isl_space * isl_set_get_space(__isl_keep isl_set *set)
Definition isl_map.c:603
__isl_export __isl_give isl_set * isl_set_union(__isl_take isl_set *set1, __isl_take isl_set *set2)
Definition isl_map.c:8281
isl_size isl_set_n_param(__isl_keep isl_set *set)
Definition isl_map.c:227
__isl_export __isl_give isl_set * isl_set_complement(__isl_take isl_set *set)
__isl_null isl_set * isl_set_free(__isl_take isl_set *set)
Definition isl_map.c:3513
__isl_give isl_set * isl_set_copy(__isl_keep isl_set *set)
Definition isl_map.c:1470
__isl_give isl_set * isl_set_project_out(__isl_take isl_set *set, enum isl_dim_type type, unsigned first, unsigned n)
Definition isl_map.c:4639
__isl_export isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
Definition isl_map.c:11257
__isl_export __isl_give isl_set * isl_set_intersect(__isl_take isl_set *set1, __isl_take isl_set *set2)
Definition isl_map.c:3965
__isl_give isl_id * isl_set_get_dim_id(__isl_keep isl_set *set, enum isl_dim_type type, unsigned pos)
Definition isl_map.c:1003
__isl_export __isl_give isl_set * isl_set_empty(__isl_take isl_space *space)
Definition isl_map.c:6343
__isl_export __isl_give isl_set * isl_set_params(__isl_take isl_set *set)
Definition isl_map.c:5948
__isl_give isl_space * isl_space_set_alloc(isl_ctx *ctx, unsigned nparam, unsigned dim)
Definition isl_space.c:156
@ isl_dim_param
Definition space_type.h:15
Helper struct to remember assumptions.
Definition ScopHelper.h:60
Type for equivalent invariant accesses and their domain context.
Definition ScopInfo.h:1101
MemoryAccessList InvariantAccesses
Memory accesses now treated invariant.
Definition ScopInfo.h:1110
static TupleKindPtr Domain("Domain")