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<const SCEV *, 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 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1480
1481 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1482 for (auto *Subscript : Subscripts) {
1483 InvariantLoadsSetTy AccessILS;
1484 if (!isAffineExpr(&scop->getRegion(), SurroundingLoop, Subscript, SE,
1485 &AccessILS))
1486 return false;
1487
1488 for (LoadInst *LInst : AccessILS)
1489 if (!ScopRIL.count(LInst))
1490 return false;
1491 }
1492
1493 if (Sizes.empty())
1494 return false;
1495
1496 std::vector<const SCEV *> SizesSCEV;
1497 SizesSCEV.push_back(nullptr);
1498 SizesSCEV.insert(SizesSCEV.end(), Sizes.begin(), Sizes.end());
1499
1500 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1501 true, Subscripts, SizesSCEV, Val);
1502 return true;
1503}
1504
1506 // Memory builtins are not considered by this function.
1507 if (!Inst.isLoad() && !Inst.isStore())
1508 return false;
1509
1510 if (!PollyDelinearize)
1511 return false;
1512
1513 Value *Address = Inst.getPointerOperand();
1514 Value *Val = Inst.getValueOperand();
1515 Type *ElementType = Val->getType();
1516 unsigned ElementSize = DL.getTypeAllocSize(ElementType);
1517 enum MemoryAccess::AccessType AccType =
1518 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
1519
1520 const SCEV *AccessFunction =
1521 SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
1522 const SCEVUnknown *BasePointer =
1523 dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
1524
1525 assert(BasePointer && "Could not find base pointer");
1526
1527 auto &InsnToMemAcc = scop->getInsnToMemAccMap();
1528 auto AccItr = InsnToMemAcc.find(Inst);
1529 if (AccItr == InsnToMemAcc.end())
1530 return false;
1531
1532 std::vector<const SCEV *> Sizes = {nullptr};
1533
1534 Sizes.insert(Sizes.end(), AccItr->second.Shape->DelinearizedSizes.begin(),
1535 AccItr->second.Shape->DelinearizedSizes.end());
1536
1537 // In case only the element size is contained in the 'Sizes' array, the
1538 // access does not access a real multi-dimensional array. Hence, we allow
1539 // the normal single-dimensional access construction to handle this.
1540 if (Sizes.size() == 1)
1541 return false;
1542
1543 // Remove the element size. This information is already provided by the
1544 // ElementSize parameter. In case the element size of this access and the
1545 // element size used for delinearization differs the delinearization is
1546 // incorrect. Hence, we invalidate the scop.
1547 //
1548 // TODO: Handle delinearization with differing element sizes.
1549 auto DelinearizedSize =
1550 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
1551 Sizes.pop_back();
1552 if (ElementSize != DelinearizedSize)
1553 scop->invalidate(DELINEARIZATION, Inst->getDebugLoc(), Inst->getParent());
1554
1555 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1556 true, AccItr->second.DelinearizedSubscripts, Sizes, Val);
1557 return true;
1558}
1559
1561 auto *MemIntr = dyn_cast_or_null<MemIntrinsic>(Inst);
1562
1563 if (MemIntr == nullptr)
1564 return false;
1565
1566 auto *L = LI.getLoopFor(Inst->getParent());
1567 const SCEV *LengthVal = SE.getSCEVAtScope(MemIntr->getLength(), L);
1568 assert(LengthVal);
1569
1570 // Check if the length val is actually affine or if we overapproximate it
1571 InvariantLoadsSetTy AccessILS;
1572 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1573
1574 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1575 bool LengthIsAffine = isAffineExpr(&scop->getRegion(), SurroundingLoop,
1576 LengthVal, SE, &AccessILS);
1577 for (LoadInst *LInst : AccessILS)
1578 if (!ScopRIL.count(LInst))
1579 LengthIsAffine = false;
1580 if (!LengthIsAffine)
1581 LengthVal = nullptr;
1582
1583 auto *DestPtrVal = MemIntr->getDest();
1584 assert(DestPtrVal);
1585
1586 const SCEV *DestAccFunc = SE.getSCEVAtScope(DestPtrVal, L);
1587 assert(DestAccFunc);
1588 // Ignore accesses to "NULL".
1589 // TODO: We could use this to optimize the region further, e.g., intersect
1590 // the context with
1591 // isl_set_complement(isl_set_params(getDomain()))
1592 // as we know it would be undefined to execute this instruction anyway.
1593 if (DestAccFunc->isZero())
1594 return true;
1595
1596 if (auto *U = dyn_cast<SCEVUnknown>(DestAccFunc)) {
1597 if (isa<ConstantPointerNull>(U->getValue()))
1598 return true;
1599 }
1600
1601 auto *DestPtrSCEV = dyn_cast<SCEVUnknown>(SE.getPointerBase(DestAccFunc));
1602 assert(DestPtrSCEV);
1603 DestAccFunc = SE.getMinusSCEV(DestAccFunc, DestPtrSCEV);
1604 addArrayAccess(Stmt, Inst, MemoryAccess::MUST_WRITE, DestPtrSCEV->getValue(),
1605 IntegerType::getInt8Ty(DestPtrVal->getContext()),
1606 LengthIsAffine, {DestAccFunc, LengthVal}, {nullptr},
1607 Inst.getValueOperand());
1608
1609 auto *MemTrans = dyn_cast<MemTransferInst>(MemIntr);
1610 if (!MemTrans)
1611 return true;
1612
1613 auto *SrcPtrVal = MemTrans->getSource();
1614 assert(SrcPtrVal);
1615
1616 const SCEV *SrcAccFunc = SE.getSCEVAtScope(SrcPtrVal, L);
1617 assert(SrcAccFunc);
1618 // Ignore accesses to "NULL".
1619 // TODO: See above TODO
1620 if (SrcAccFunc->isZero())
1621 return true;
1622
1623 auto *SrcPtrSCEV = dyn_cast<SCEVUnknown>(SE.getPointerBase(SrcAccFunc));
1624 assert(SrcPtrSCEV);
1625 SrcAccFunc = SE.getMinusSCEV(SrcAccFunc, SrcPtrSCEV);
1626 addArrayAccess(Stmt, Inst, MemoryAccess::READ, SrcPtrSCEV->getValue(),
1627 IntegerType::getInt8Ty(SrcPtrVal->getContext()),
1628 LengthIsAffine, {SrcAccFunc, LengthVal}, {nullptr},
1629 Inst.getValueOperand());
1630
1631 return true;
1632}
1633
1635 auto *CI = dyn_cast_or_null<CallInst>(Inst);
1636
1637 if (CI == nullptr)
1638 return false;
1639
1640 if (CI->doesNotAccessMemory() || isIgnoredIntrinsic(CI) || isDebugCall(CI))
1641 return true;
1642
1643 const SCEV *AF = SE.getConstant(IntegerType::getInt64Ty(CI->getContext()), 0);
1644 auto *CalledFunction = CI->getCalledFunction();
1645 MemoryEffects ME = AA.getMemoryEffects(CalledFunction);
1646 if (ME.doesNotAccessMemory())
1647 return true;
1648
1649 if (ME.onlyAccessesArgPointees()) {
1650 ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
1651 auto AccType =
1652 !isModSet(ArgMR) ? MemoryAccess::READ : MemoryAccess::MAY_WRITE;
1653 Loop *L = LI.getLoopFor(Inst->getParent());
1654 for (const auto &Arg : CI->args()) {
1655 if (!Arg->getType()->isPointerTy())
1656 continue;
1657
1658 const SCEV *ArgSCEV = SE.getSCEVAtScope(Arg, L);
1659 if (ArgSCEV->isZero())
1660 continue;
1661
1662 if (auto *U = dyn_cast<SCEVUnknown>(ArgSCEV)) {
1663 if (isa<ConstantPointerNull>(U->getValue()))
1664 return true;
1665 }
1666
1667 auto *ArgBasePtr = cast<SCEVUnknown>(SE.getPointerBase(ArgSCEV));
1668 addArrayAccess(Stmt, Inst, AccType, ArgBasePtr->getValue(),
1669 ArgBasePtr->getType(), false, {AF}, {nullptr}, CI);
1670 }
1671 return true;
1672 }
1673
1674 if (ME.onlyReadsMemory()) {
1675 GlobalReads.emplace_back(Stmt, CI);
1676 return true;
1677 }
1678 return false;
1679}
1680
1682 // Memory builtins are not considered by this function.
1683 if (!Inst.isLoad() && !Inst.isStore())
1684 return false;
1685
1686 Value *Address = Inst.getPointerOperand();
1687 Value *Val = Inst.getValueOperand();
1688 Type *ElementType = Val->getType();
1689 enum MemoryAccess::AccessType AccType =
1690 isa<LoadInst>(Inst) ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
1691
1692 const SCEV *AccessFunction =
1693 SE.getSCEVAtScope(Address, LI.getLoopFor(Inst->getParent()));
1694 const SCEVUnknown *BasePointer =
1695 dyn_cast<SCEVUnknown>(SE.getPointerBase(AccessFunction));
1696
1697 assert(BasePointer && "Could not find base pointer");
1698 AccessFunction = SE.getMinusSCEV(AccessFunction, BasePointer);
1699
1700 // Check if the access depends on a loop contained in a non-affine subregion.
1701 bool isVariantInNonAffineLoop = false;
1702 SetVector<const Loop *> Loops;
1703 findLoops(AccessFunction, Loops);
1704 for (const Loop *L : Loops)
1705 if (Stmt->contains(L)) {
1706 isVariantInNonAffineLoop = true;
1707 break;
1708 }
1709
1710 InvariantLoadsSetTy AccessILS;
1711
1712 Loop *SurroundingLoop = Stmt->getSurroundingLoop();
1713 bool IsAffine = !isVariantInNonAffineLoop &&
1714 isAffineExpr(&scop->getRegion(), SurroundingLoop,
1715 AccessFunction, SE, &AccessILS);
1716
1717 const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads();
1718 for (LoadInst *LInst : AccessILS)
1719 if (!ScopRIL.count(LInst))
1720 IsAffine = false;
1721
1722 if (!IsAffine && AccType == MemoryAccess::MUST_WRITE)
1723 AccType = MemoryAccess::MAY_WRITE;
1724
1725 addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType,
1726 IsAffine, {AccessFunction}, {nullptr}, Val);
1727 return true;
1728}
1729
1731 if (buildAccessMemIntrinsic(Inst, Stmt))
1732 return;
1733
1734 if (buildAccessCallInst(Inst, Stmt))
1735 return;
1736
1737 if (buildAccessMultiDimFixed(Inst, Stmt))
1738 return;
1739
1740 if (buildAccessMultiDimParam(Inst, Stmt))
1741 return;
1742
1743 if (buildAccessSingleDim(Inst, Stmt))
1744 return;
1745
1746 llvm_unreachable(
1747 "At least one of the buildAccess functions must handled this access, or "
1748 "ScopDetection should have rejected this SCoP");
1749}
1750
1752 for (auto &Stmt : *scop) {
1753 if (Stmt.isBlockStmt()) {
1754 buildAccessFunctions(&Stmt, *Stmt.getBasicBlock());
1755 continue;
1756 }
1757
1758 Region *R = Stmt.getRegion();
1759 for (BasicBlock *BB : R->blocks())
1760 buildAccessFunctions(&Stmt, *BB, R);
1761 }
1762
1763 // Build write accesses for values that are used after the SCoP.
1764 // The instructions defining them might be synthesizable and therefore not
1765 // contained in any statement, hence we iterate over the original instructions
1766 // to identify all escaping values.
1767 for (BasicBlock *BB : scop->getRegion().blocks()) {
1768 for (Instruction &Inst : *BB)
1770 }
1771}
1772
1773bool ScopBuilder::shouldModelInst(Instruction *Inst, Loop *L) {
1774 return !Inst->isTerminator() && !isIgnoredIntrinsic(Inst) &&
1775 !canSynthesize(Inst, *scop, &SE, L);
1776}
1777
1778/// Generate a name for a statement.
1779///
1780/// @param BB The basic block the statement will represent.
1781/// @param BBIdx The index of the @p BB relative to other BBs/regions.
1782/// @param Count The index of the created statement in @p BB.
1783/// @param IsMain Whether this is the main of all statement for @p BB. If true,
1784/// no suffix will be added.
1785/// @param IsLast Uses a special indicator for the last statement of a BB.
1786static std::string makeStmtName(BasicBlock *BB, long BBIdx, int Count,
1787 bool IsMain, bool IsLast = false) {
1788 std::string Suffix;
1789 if (!IsMain) {
1791 Suffix = '_';
1792 if (IsLast)
1793 Suffix += "last";
1794 else if (Count < 26)
1795 Suffix += 'a' + Count;
1796 else
1797 Suffix += std::to_string(Count);
1798 }
1799 return getIslCompatibleName("Stmt", BB, BBIdx, Suffix, UseInstructionNames);
1800}
1801
1802/// Generate a name for a statement that represents a non-affine subregion.
1803///
1804/// @param R The region the statement will represent.
1805/// @param RIdx The index of the @p R relative to other BBs/regions.
1806static std::string makeStmtName(Region *R, long RIdx) {
1807 return getIslCompatibleName("Stmt", R->getNameStr(), RIdx, "",
1809}
1810
1811void ScopBuilder::buildSequentialBlockStmts(BasicBlock *BB, bool SplitOnStore) {
1812 Loop *SurroundingLoop = LI.getLoopFor(BB);
1813
1814 int Count = 0;
1815 long BBIdx = scop->getNextStmtIdx();
1816 std::vector<Instruction *> Instructions;
1817 for (Instruction &Inst : *BB) {
1818 if (shouldModelInst(&Inst, SurroundingLoop))
1819 Instructions.push_back(&Inst);
1820 if (Inst.getMetadata("polly_split_after") ||
1821 (SplitOnStore && isa<StoreInst>(Inst))) {
1822 std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0);
1823 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1824 Count++;
1825 Instructions.clear();
1826 }
1827 }
1828
1829 std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0);
1830 scop->addScopStmt(BB, Name, SurroundingLoop, Instructions);
1831}
1832
1833/// Is @p Inst an ordered instruction?
1834///
1835/// An unordered instruction is an instruction, such that a sequence of
1836/// unordered instructions can be permuted without changing semantics. Any
1837/// instruction for which this is not always the case is ordered.
1838static bool isOrderedInstruction(Instruction *Inst) {
1839 return Inst->mayHaveSideEffects() || Inst->mayReadOrWriteMemory();
1840}
1841
1842/// Join instructions to the same statement if one uses the scalar result of the
1843/// other.
1844static void joinOperandTree(EquivalenceClasses<Instruction *> &UnionFind,
1845 ArrayRef<Instruction *> ModeledInsts) {
1846 for (Instruction *Inst : ModeledInsts) {
1847 if (isa<PHINode>(Inst))
1848 continue;
1849
1850 for (Use &Op : Inst->operands()) {
1851 Instruction *OpInst = dyn_cast<Instruction>(Op.get());
1852 if (!OpInst)
1853 continue;
1854
1855 // Check if OpInst is in the BB and is a modeled instruction.
1856 if (!UnionFind.contains(OpInst))
1857 continue;
1858
1859 UnionFind.unionSets(Inst, OpInst);
1860 }
1861 }
1862}
1863
1864/// Ensure that the order of ordered instructions does not change.
1865///
1866/// If we encounter an ordered instruction enclosed in instructions belonging to
1867/// a different statement (which might as well contain ordered instructions, but
1868/// this is not tested here), join them.
1869static void
1870joinOrderedInstructions(EquivalenceClasses<Instruction *> &UnionFind,
1871 ArrayRef<Instruction *> ModeledInsts) {
1872 SetVector<Instruction *> SeenLeaders;
1873 for (Instruction *Inst : ModeledInsts) {
1874 if (!isOrderedInstruction(Inst))
1875 continue;
1876
1877 Instruction *Leader = UnionFind.getLeaderValue(Inst);
1878 // Since previous iterations might have merged sets, some items in
1879 // SeenLeaders are not leaders anymore. However, The new leader of
1880 // previously merged instructions must be one of the former leaders of
1881 // these merged instructions.
1882 bool Inserted = SeenLeaders.insert(Leader);
1883 if (Inserted)
1884 continue;
1885
1886 // Merge statements to close holes. Say, we have already seen statements A
1887 // and B, in this order. Then we see an instruction of A again and we would
1888 // see the pattern "A B A". This function joins all statements until the
1889 // only seen occurrence of A.
1890 for (Instruction *Prev : reverse(SeenLeaders)) {
1891 // We are backtracking from the last element until we see Inst's leader
1892 // in SeenLeaders and merge all into one set. Although leaders of
1893 // instructions change during the execution of this loop, it's irrelevant
1894 // as we are just searching for the element that we already confirmed is
1895 // in the list.
1896 if (Prev == Leader)
1897 break;
1898 UnionFind.unionSets(Prev, Leader);
1899 }
1900 }
1901}
1902
1903/// If the BasicBlock has an edge from itself, ensure that the PHI WRITEs for
1904/// the incoming values from this block are executed after the PHI READ.
1905///
1906/// Otherwise it could overwrite the incoming value from before the BB with the
1907/// value for the next execution. This can happen if the PHI WRITE is added to
1908/// the statement with the instruction that defines the incoming value (instead
1909/// of the last statement of the same BB). To ensure that the PHI READ and WRITE
1910/// are in order, we put both into the statement. PHI WRITEs are always executed
1911/// after PHI READs when they are in the same statement.
1912///
1913/// TODO: This is an overpessimization. We only have to ensure that the PHI
1914/// WRITE is not put into a statement containing the PHI itself. That could also
1915/// be done by
1916/// - having all (strongly connected) PHIs in a single statement,
1917/// - unite only the PHIs in the operand tree of the PHI WRITE (because it only
1918/// has a chance of being lifted before a PHI by being in a statement with a
1919/// PHI that comes before in the basic block), or
1920/// - when uniting statements, ensure that no (relevant) PHIs are overtaken.
1921static void joinOrderedPHIs(EquivalenceClasses<Instruction *> &UnionFind,
1922 ArrayRef<Instruction *> ModeledInsts) {
1923 for (Instruction *Inst : ModeledInsts) {
1924 PHINode *PHI = dyn_cast<PHINode>(Inst);
1925 if (!PHI)
1926 continue;
1927
1928 int Idx = PHI->getBasicBlockIndex(PHI->getParent());
1929 if (Idx < 0)
1930 continue;
1931
1932 Instruction *IncomingVal =
1933 dyn_cast<Instruction>(PHI->getIncomingValue(Idx));
1934 if (!IncomingVal)
1935 continue;
1936
1937 UnionFind.unionSets(PHI, IncomingVal);
1938 }
1939}
1940
1942 Loop *L = LI.getLoopFor(BB);
1943
1944 // Extracting out modeled instructions saves us from checking
1945 // shouldModelInst() repeatedly.
1946 SmallVector<Instruction *, 32> ModeledInsts;
1947 EquivalenceClasses<Instruction *> UnionFind;
1948 Instruction *MainInst = nullptr, *MainLeader = nullptr;
1949 for (Instruction &Inst : *BB) {
1950 if (!shouldModelInst(&Inst, L))
1951 continue;
1952 ModeledInsts.push_back(&Inst);
1953 UnionFind.insert(&Inst);
1954
1955 // When a BB is split into multiple statements, the main statement is the
1956 // one containing the 'main' instruction. We select the first instruction
1957 // that is unlikely to be removed (because it has side-effects) as the main
1958 // one. It is used to ensure that at least one statement from the bb has the
1959 // same name as with -polly-stmt-granularity=bb.
1960 if (!MainInst && (isa<StoreInst>(Inst) ||
1961 (isa<CallInst>(Inst) && !isa<IntrinsicInst>(Inst))))
1962 MainInst = &Inst;
1963 }
1964
1965 joinOperandTree(UnionFind, ModeledInsts);
1966 joinOrderedInstructions(UnionFind, ModeledInsts);
1967 joinOrderedPHIs(UnionFind, ModeledInsts);
1968
1969 // The list of instructions for statement (statement represented by the leader
1970 // instruction).
1971 MapVector<Instruction *, std::vector<Instruction *>> LeaderToInstList;
1972
1973 // The order of statements must be preserved w.r.t. their ordered
1974 // instructions. Without this explicit scan, we would also use non-ordered
1975 // instructions (whose order is arbitrary) to determine statement order.
1976 for (Instruction *Inst : ModeledInsts) {
1977 if (!isOrderedInstruction(Inst))
1978 continue;
1979
1980 auto LeaderIt = UnionFind.findLeader(Inst);
1981 if (LeaderIt == UnionFind.member_end())
1982 continue;
1983
1984 // Insert element for the leader instruction.
1985 (void)LeaderToInstList[*LeaderIt];
1986 }
1987
1988 // Collect the instructions of all leaders. UnionFind's member iterator
1989 // unfortunately are not in any specific order.
1990 for (Instruction *Inst : ModeledInsts) {
1991 auto LeaderIt = UnionFind.findLeader(Inst);
1992 if (LeaderIt == UnionFind.member_end())
1993 continue;
1994
1995 if (Inst == MainInst)
1996 MainLeader = *LeaderIt;
1997 std::vector<Instruction *> &InstList = LeaderToInstList[*LeaderIt];
1998 InstList.push_back(Inst);
1999 }
2000
2001 // Finally build the statements.
2002 int Count = 0;
2003 long BBIdx = scop->getNextStmtIdx();
2004 for (auto &Instructions : LeaderToInstList) {
2005 std::vector<Instruction *> &InstList = Instructions.second;
2006
2007 // If there is no main instruction, make the first statement the main.
2008 bool IsMain = (MainInst ? MainLeader == Instructions.first : Count == 0);
2009
2010 std::string Name = makeStmtName(BB, BBIdx, Count, IsMain);
2011 scop->addScopStmt(BB, Name, L, std::move(InstList));
2012 Count += 1;
2013 }
2014
2015 // Unconditionally add an epilogue (last statement). It contains no
2016 // instructions, but holds the PHI write accesses for successor basic blocks,
2017 // if the incoming value is not defined in another statement if the same BB.
2018 // The epilogue becomes the main statement only if there is no other
2019 // statement that could become main.
2020 // The epilogue will be removed if no PHIWrite is added to it.
2021 std::string EpilogueName = makeStmtName(BB, BBIdx, Count, Count == 0, true);
2022 scop->addScopStmt(BB, EpilogueName, L, {});
2023}
2024
2025void ScopBuilder::buildStmts(Region &SR) {
2026 if (scop->isNonAffineSubRegion(&SR)) {
2027 std::vector<Instruction *> Instructions;
2028 Loop *SurroundingLoop =
2029 getFirstNonBoxedLoopFor(SR.getEntry(), LI, scop->getBoxedLoops());
2030 for (Instruction &Inst : *SR.getEntry())
2031 if (shouldModelInst(&Inst, SurroundingLoop))
2032 Instructions.push_back(&Inst);
2033 long RIdx = scop->getNextStmtIdx();
2034 std::string Name = makeStmtName(&SR, RIdx);
2035 scop->addScopStmt(&SR, Name, SurroundingLoop, Instructions);
2036 return;
2037 }
2038
2039 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
2040 if (I->isSubRegion())
2041 buildStmts(*I->getNodeAs<Region>());
2042 else {
2043 BasicBlock *BB = I->getNodeAs<BasicBlock>();
2044 switch (StmtGranularity) {
2047 break;
2050 break;
2052 buildSequentialBlockStmts(BB, true);
2053 break;
2054 }
2055 }
2056}
2057
2059 Region *NonAffineSubRegion) {
2060 assert(
2061 Stmt &&
2062 "The exit BB is the only one that cannot be represented by a statement");
2063 assert(Stmt->represents(&BB));
2064
2065 // We do not build access functions for error blocks, as they may contain
2066 // instructions we can not model.
2067 if (SD.isErrorBlock(BB, scop->getRegion()))
2068 return;
2069
2070 auto BuildAccessesForInst = [this, Stmt,
2071 NonAffineSubRegion](Instruction *Inst) {
2072 PHINode *PHI = dyn_cast<PHINode>(Inst);
2073 if (PHI)
2074 buildPHIAccesses(Stmt, PHI, NonAffineSubRegion, false);
2075
2076 if (auto MemInst = MemAccInst::dyn_cast(*Inst)) {
2077 assert(Stmt && "Cannot build access function in non-existing statement");
2078 buildMemoryAccess(MemInst, Stmt);
2079 }
2080
2081 // PHI nodes have already been modeled above and terminators that are
2082 // not part of a non-affine subregion are fully modeled and regenerated
2083 // from the polyhedral domains. Hence, they do not need to be modeled as
2084 // explicit data dependences.
2085 if (!PHI)
2086 buildScalarDependences(Stmt, Inst);
2087 };
2088
2089 const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
2090 bool IsEntryBlock = (Stmt->getEntryBlock() == &BB);
2091 if (IsEntryBlock) {
2092 for (Instruction *Inst : Stmt->getInstructions())
2093 BuildAccessesForInst(Inst);
2094 if (Stmt->isRegionStmt())
2095 BuildAccessesForInst(BB.getTerminator());
2096 } else {
2097 for (Instruction &Inst : BB) {
2098 if (isIgnoredIntrinsic(&Inst))
2099 continue;
2100
2101 // Invariant loads already have been processed.
2102 if (isa<LoadInst>(Inst) && RIL.count(cast<LoadInst>(&Inst)))
2103 continue;
2104
2105 BuildAccessesForInst(&Inst);
2106 }
2107 }
2108}
2109
2111 ScopStmt *Stmt, Instruction *Inst, MemoryAccess::AccessType AccType,
2112 Value *BaseAddress, Type *ElementType, bool Affine, Value *AccessValue,
2113 ArrayRef<const SCEV *> Subscripts, ArrayRef<const SCEV *> Sizes,
2114 MemoryKind Kind) {
2115 bool isKnownMustAccess = false;
2116
2117 // Accesses in single-basic block statements are always executed.
2118 if (Stmt->isBlockStmt())
2119 isKnownMustAccess = true;
2120
2121 if (Stmt->isRegionStmt()) {
2122 // Accesses that dominate the exit block of a non-affine region are always
2123 // executed. In non-affine regions there may exist MemoryKind::Values that
2124 // do not dominate the exit. MemoryKind::Values will always dominate the
2125 // exit and MemoryKind::PHIs only if there is at most one PHI_WRITE in the
2126 // non-affine region.
2127 if (Inst && DT.dominates(Inst->getParent(), Stmt->getRegion()->getExit()))
2128 isKnownMustAccess = true;
2129 }
2130
2131 // Non-affine PHI writes do not "happen" at a particular instruction, but
2132 // after exiting the statement. Therefore they are guaranteed to execute and
2133 // overwrite the old value.
2135 isKnownMustAccess = true;
2136
2137 if (!isKnownMustAccess && AccType == MemoryAccess::MUST_WRITE)
2138 AccType = MemoryAccess::MAY_WRITE;
2139
2140 auto *Access = new MemoryAccess(Stmt, Inst, AccType, BaseAddress, ElementType,
2141 Affine, Subscripts, Sizes, AccessValue, Kind);
2142
2143 scop->addAccessFunction(Access);
2144 Stmt->addAccess(Access);
2145 return Access;
2146}
2147
2150 Value *BaseAddress, Type *ElementType,
2151 bool IsAffine,
2152 ArrayRef<const SCEV *> Subscripts,
2153 ArrayRef<const SCEV *> Sizes,
2154 Value *AccessValue) {
2155 ArrayBasePointers.insert(BaseAddress);
2156 addMemoryAccess(Stmt, MemAccInst, AccType, BaseAddress, ElementType, IsAffine,
2157 AccessValue, Subscripts, Sizes, MemoryKind::Array);
2158}
2159
2160/// Check if @p Expr is divisible by @p Size.
2161static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) {
2162 assert(Size != 0);
2163 if (Size == 1)
2164 return true;
2165
2166 // Only one factor needs to be divisible.
2167 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
2168 for (const SCEV *FactorExpr : MulExpr->operands())
2169 if (isDivisible(FactorExpr, Size, SE))
2170 return true;
2171 return false;
2172 }
2173
2174 // For other n-ary expressions (Add, AddRec, Max,...) all operands need
2175 // to be divisible.
2176 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
2177 for (const SCEV *OpExpr : NAryExpr->operands())
2178 if (!isDivisible(OpExpr, Size, SE))
2179 return false;
2180 return true;
2181 }
2182
2183 const SCEV *SizeSCEV = SE.getConstant(Expr->getType(), Size);
2184 const SCEV *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
2185 const SCEV *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
2186 return MulSCEV == Expr;
2187}
2188
2190 isl::union_set Accessed = scop->getAccesses().range();
2191
2192 for (auto Array : scop->arrays()) {
2193 if (Array->getNumberOfDimensions() <= 1)
2194 continue;
2195
2196 isl::space Space = Array->getSpace();
2197 Space = Space.align_params(Accessed.get_space());
2198
2199 if (!Accessed.contains(Space))
2200 continue;
2201
2202 isl::set Elements = Accessed.extract_set(Space);
2203 isl::map Transform = isl::map::universe(Array->getSpace().map_from_set());
2204
2205 std::vector<int> Int;
2206 unsigned Dims = unsignedFromIslSize(Elements.tuple_dim());
2207 for (unsigned i = 0; i < Dims; i++) {
2208 isl::set DimOnly = isl::set(Elements).project_out(isl::dim::set, 0, i);
2209 DimOnly = DimOnly.project_out(isl::dim::set, 1, Dims - i - 1);
2210 DimOnly = DimOnly.lower_bound_si(isl::dim::set, 0, 0);
2211
2212 isl::basic_set DimHull = DimOnly.affine_hull();
2213
2214 if (i == Dims - 1) {
2215 Int.push_back(1);
2216 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
2217 continue;
2218 }
2219
2220 if (unsignedFromIslSize(DimHull.dim(isl::dim::div)) == 1) {
2221 isl::aff Diff = DimHull.get_div(0);
2222 isl::val Val = Diff.get_denominator_val();
2223
2224 int ValInt = 1;
2225 if (Val.is_int()) {
2226 auto ValAPInt = APIntFromVal(Val);
2227 if (ValAPInt.isSignedIntN(32))
2228 ValInt = ValAPInt.getSExtValue();
2229 } else {
2230 }
2231
2232 Int.push_back(ValInt);
2234 isl::local_space(Transform.get_space()));
2235 C = C.set_coefficient_si(isl::dim::out, i, ValInt);
2236 C = C.set_coefficient_si(isl::dim::in, i, -1);
2237 Transform = Transform.add_constraint(C);
2238 continue;
2239 }
2240
2241 isl::basic_set ZeroSet = isl::basic_set(DimHull);
2242 ZeroSet = ZeroSet.fix_si(isl::dim::set, 0, 0);
2243
2244 int ValInt = 1;
2245 if (ZeroSet.is_equal(DimHull)) {
2246 ValInt = 0;
2247 }
2248
2249 Int.push_back(ValInt);
2250 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
2251 }
2252
2253 isl::set MappedElements = isl::map(Transform).domain();
2254 if (!Elements.is_subset(MappedElements))
2255 continue;
2256
2257 bool CanFold = true;
2258 if (Int[0] <= 1)
2259 CanFold = false;
2260
2261 unsigned NumDims = Array->getNumberOfDimensions();
2262 for (unsigned i = 1; i < NumDims - 1; i++)
2263 if (Int[0] != Int[i] && Int[i])
2264 CanFold = false;
2265
2266 if (!CanFold)
2267 continue;
2268
2269 for (auto &Access : scop->access_functions())
2270 if (Access->getScopArrayInfo() == Array)
2271 Access->setAccessRelation(
2272 Access->getAccessRelation().apply_range(Transform));
2273
2274 std::vector<const SCEV *> Sizes;
2275 for (unsigned i = 0; i < NumDims; i++) {
2276 auto Size = Array->getDimensionSize(i);
2277
2278 if (i == NumDims - 1)
2279 Size = SE.getMulExpr(Size, SE.getConstant(Size->getType(), Int[0]));
2280 Sizes.push_back(Size);
2281 }
2282
2283 Array->updateSizes(Sizes, false /* CheckConsistency */);
2284 }
2285}
2286
2293
2295 // Check all array accesses for each base pointer and find a (virtual) element
2296 // size for the base pointer that divides all access functions.
2297 for (ScopStmt &Stmt : *scop)
2298 for (MemoryAccess *Access : Stmt) {
2299 if (!Access->isArrayKind())
2300 continue;
2302 const_cast<ScopArrayInfo *>(Access->getScopArrayInfo());
2303
2304 if (Array->getNumberOfDimensions() != 1)
2305 continue;
2306 unsigned DivisibleSize = Array->getElemSizeInBytes();
2307 const SCEV *Subscript = Access->getSubscript(0);
2308 while (!isDivisible(Subscript, DivisibleSize, SE))
2309 DivisibleSize /= 2;
2310 auto *Ty = IntegerType::get(SE.getContext(), DivisibleSize * 8);
2311 Array->updateElementType(Ty);
2312 }
2313
2314 for (auto &Stmt : *scop)
2315 for (auto &Access : Stmt)
2316 Access->updateDimensionality();
2317}
2318
2320 for (auto &Stmt : *scop)
2321 for (auto &Access : Stmt)
2322 Access->foldAccessRelation();
2323}
2324
2327 return;
2328 for (auto &Stmt : *scop)
2329 for (auto &Access : Stmt) {
2330 isl::set Outside = Access->assumeNoOutOfBound();
2331 const auto &Loc = Access->getAccessInstruction()
2332 ? Access->getAccessInstruction()->getDebugLoc()
2333 : DebugLoc();
2336 }
2337}
2338
2339void ScopBuilder::ensureValueWrite(Instruction *Inst) {
2340 // Find the statement that defines the value of Inst. That statement has to
2341 // write the value to make it available to those statements that read it.
2342 ScopStmt *Stmt = scop->getStmtFor(Inst);
2343
2344 // It is possible that the value is synthesizable within a loop (such that it
2345 // is not part of any statement), but not after the loop (where you need the
2346 // number of loop round-trips to synthesize it). In LCSSA-form a PHI node will
2347 // avoid this. In case the IR has no such PHI, use the last statement (where
2348 // the value is synthesizable) to write the value.
2349 if (!Stmt)
2350 Stmt = scop->getLastStmtFor(Inst->getParent());
2351
2352 // Inst not defined within this SCoP.
2353 if (!Stmt)
2354 return;
2355
2356 // Do not process further if the instruction is already written.
2357 if (Stmt->lookupValueWriteOf(Inst))
2358 return;
2359
2360 addMemoryAccess(Stmt, Inst, MemoryAccess::MUST_WRITE, Inst, Inst->getType(),
2361 true, Inst, ArrayRef<const SCEV *>(),
2362 ArrayRef<const SCEV *>(), MemoryKind::Value);
2363}
2364
2366 // TODO: Make ScopStmt::ensureValueRead(Value*) offer the same functionality
2367 // to be able to replace this one. Currently, there is a split responsibility.
2368 // In a first step, the MemoryAccess is created, but without the
2369 // AccessRelation. In the second step by ScopStmt::buildAccessRelations(), the
2370 // AccessRelation is created. At least for scalar accesses, there is no new
2371 // information available at ScopStmt::buildAccessRelations(), so we could
2372 // create the AccessRelation right away. This is what
2373 // ScopStmt::ensureValueRead(Value*) does.
2374
2375 auto *Scope = UserStmt->getSurroundingLoop();
2376 auto VUse = VirtualUse::create(scop.get(), UserStmt, Scope, V, false);
2377 switch (VUse.getKind()) {
2379 case VirtualUse::Block:
2382 case VirtualUse::Intra:
2383 // Uses of these kinds do not need a MemoryAccess.
2384 break;
2385
2387 // Add MemoryAccess for invariant values only if requested.
2389 break;
2390
2391 [[fallthrough]];
2392 case VirtualUse::Inter:
2393
2394 // Do not create another MemoryAccess for reloading the value if one already
2395 // exists.
2396 if (UserStmt->lookupValueReadOf(V))
2397 break;
2398
2399 addMemoryAccess(UserStmt, nullptr, MemoryAccess::READ, V, V->getType(),
2400 true, V, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2402
2403 // Inter-statement uses need to write the value in their defining statement.
2404 if (VUse.isInter())
2405 ensureValueWrite(cast<Instruction>(V));
2406 break;
2407 }
2408}
2409
2410void ScopBuilder::ensurePHIWrite(PHINode *PHI, ScopStmt *IncomingStmt,
2411 BasicBlock *IncomingBlock,
2412 Value *IncomingValue, bool IsExitBlock) {
2413 // As the incoming block might turn out to be an error statement ensure we
2414 // will create an exit PHI SAI object. It is needed during code generation
2415 // and would be created later anyway.
2416 if (IsExitBlock)
2417 scop->getOrCreateScopArrayInfo(PHI, PHI->getType(), {},
2419
2420 // This is possible if PHI is in the SCoP's entry block. The incoming blocks
2421 // from outside the SCoP's region have no statement representation.
2422 if (!IncomingStmt)
2423 return;
2424
2425 // Take care for the incoming value being available in the incoming block.
2426 // This must be done before the check for multiple PHI writes because multiple
2427 // exiting edges from subregion each can be the effective written value of the
2428 // subregion. As such, all of them must be made available in the subregion
2429 // statement.
2430 ensureValueRead(IncomingValue, IncomingStmt);
2431
2432 // Do not add more than one MemoryAccess per PHINode and ScopStmt.
2433 if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) {
2434 assert(Acc->getAccessInstruction() == PHI);
2435 Acc->addIncoming(IncomingBlock, IncomingValue);
2436 return;
2437 }
2438
2440 IncomingStmt, PHI, MemoryAccess::MUST_WRITE, PHI, PHI->getType(), true,
2441 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2442 IsExitBlock ? MemoryKind::ExitPHI : MemoryKind::PHI);
2443 assert(Acc);
2444 Acc->addIncoming(IncomingBlock, IncomingValue);
2445}
2446
2448 addMemoryAccess(PHIStmt, PHI, MemoryAccess::READ, PHI, PHI->getType(), true,
2449 PHI, ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
2451}
2452
2454 isl::id Id = isl::id::alloc(scop->getIslCtx(), Stmt.getBaseName(), &Stmt);
2455
2456 Stmt.Domain = scop->getDomainConditions(&Stmt);
2457 Stmt.Domain = Stmt.Domain.set_tuple_id(Id);
2458}
2459
2461 isl::set Domain = Stmt.getDomain();
2462 BasicBlock *BB = Stmt.getEntryBlock();
2463
2464 Loop *L = LI.getLoopFor(BB);
2465
2466 while (L && Stmt.isRegionStmt() && Stmt.getRegion()->contains(L))
2467 L = L->getParentLoop();
2468
2469 SmallVector<llvm::Loop *, 8> Loops;
2470
2471 while (L && Stmt.getParent()->getRegion().contains(L)) {
2472 Loops.push_back(L);
2473 L = L->getParentLoop();
2474 }
2475
2476 Stmt.NestLoops.insert(Stmt.NestLoops.begin(), Loops.rbegin(), Loops.rend());
2477}
2478
2479/// Return the reduction type for a given binary operator.
2481getReductionType(const BinaryOperator *BinOp) {
2482 if (!BinOp)
2483 return MemoryAccess::RT_NONE;
2484 switch (BinOp->getOpcode()) {
2485 case Instruction::FAdd:
2486 if (!BinOp->isFast())
2487 return MemoryAccess::RT_NONE;
2488 [[fallthrough]];
2489 case Instruction::Add:
2490 return MemoryAccess::RT_ADD;
2491 case Instruction::Or:
2492 return MemoryAccess::RT_BOR;
2493 case Instruction::Xor:
2494 return MemoryAccess::RT_BXOR;
2495 case Instruction::And:
2496 return MemoryAccess::RT_BAND;
2497 case Instruction::FMul:
2498 if (!BinOp->isFast())
2499 return MemoryAccess::RT_NONE;
2500 [[fallthrough]];
2501 case Instruction::Mul:
2503 return MemoryAccess::RT_NONE;
2504 return MemoryAccess::RT_MUL;
2505 default:
2506 return MemoryAccess::RT_NONE;
2507 }
2508}
2509
2510/// @brief Combine two reduction types
2514 if (RT0 == MemoryAccess::RT_BOTTOM)
2515 return RT1;
2516 if (RT0 == RT1)
2517 return RT1;
2518 return MemoryAccess::RT_NONE;
2519}
2520
2521/// True if @p AllAccs intersects with @p MemAccs except @p LoadMA and @p
2522/// StoreMA
2524 MemoryAccess *StoreMA, isl::set Domain,
2525 SmallVector<MemoryAccess *, 8> &MemAccs) {
2526 bool HasIntersectingAccs = false;
2527 auto AllAccsNoParams = AllAccs.project_out_all_params();
2528
2529 for (MemoryAccess *MA : MemAccs) {
2530 if (MA == LoadMA || MA == StoreMA)
2531 continue;
2532 auto AccRel = MA->getAccessRelation().intersect_domain(Domain);
2533 auto Accs = AccRel.range();
2534 auto AccsNoParams = Accs.project_out_all_params();
2535
2536 bool CompatibleSpace = AllAccsNoParams.has_equal_space(AccsNoParams);
2537
2538 if (CompatibleSpace) {
2539 auto OverlapAccs = Accs.intersect(AllAccs);
2540 bool DoesIntersect = !OverlapAccs.is_empty();
2541 HasIntersectingAccs |= DoesIntersect;
2542 }
2543 }
2544 return HasIntersectingAccs;
2545}
2546
2547/// Test if the accesses of @p LoadMA and @p StoreMA can form a reduction
2550 SmallVector<MemoryAccess *, 8> &MemAccs) {
2551 // First check if the base value is the same.
2552 isl::map LoadAccs = LoadMA->getAccessRelation();
2553 isl::map StoreAccs = StoreMA->getAccessRelation();
2554 bool Valid = LoadAccs.has_equal_space(StoreAccs);
2555 POLLY_DEBUG(dbgs() << " == The accessed space below is "
2556 << (Valid ? "" : "not ") << "equal!\n");
2557 POLLY_DEBUG(LoadMA->dump(); StoreMA->dump());
2558
2559 if (Valid) {
2560 // Then check if they actually access the same memory.
2561 isl::map R = isl::manage(LoadAccs.copy())
2562 .intersect_domain(isl::manage(Domain.copy()));
2563 isl::map W = isl::manage(StoreAccs.copy())
2564 .intersect_domain(isl::manage(Domain.copy()));
2565 isl::set RS = R.range();
2566 isl::set WS = W.range();
2567
2568 isl::set InterAccs =
2569 isl::manage(RS.copy()).intersect(isl::manage(WS.copy()));
2570 Valid = !InterAccs.is_empty();
2571 POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "" : "not ")
2572 << "overlapping!\n");
2573 }
2574
2575 if (Valid) {
2576 // Finally, check if they are no other instructions accessing this memory
2577 isl::map AllAccsRel = LoadAccs.unite(StoreAccs);
2578 AllAccsRel = AllAccsRel.intersect_domain(Domain);
2579 isl::set AllAccs = AllAccsRel.range();
2580 Valid = !hasIntersectingAccesses(AllAccs, LoadMA, StoreMA, Domain, MemAccs);
2581 POLLY_DEBUG(dbgs() << " == The accessed memory is " << (Valid ? "not " : "")
2582 << "accessed by other instructions!\n");
2583 }
2584
2585 return Valid;
2586}
2587
2589 // Perform a data flow analysis on the current scop statement to propagate the
2590 // uses of loaded values. Then check and mark the memory accesses which are
2591 // part of reduction like chains.
2592 // During the data flow analysis we use the State variable to keep track of
2593 // the used "load-instructions" for each instruction in the scop statement.
2594 // This includes the LLVM-IR of the load and the "number of uses" (or the
2595 // number of paths in the operand tree which end in this load).
2596 using StatePairTy = std::pair<unsigned, MemoryAccess::ReductionType>;
2597 using FlowInSetTy = MapVector<const LoadInst *, StatePairTy>;
2598 using StateTy = MapVector<const Instruction *, FlowInSetTy>;
2599 StateTy State;
2600
2601 // Invalid loads are loads which have uses we can't track properly in the
2602 // state map. This includes loads which:
2603 // o do not form a reduction when they flow into a memory location:
2604 // (e.g., A[i] = B[i] * 3 and A[i] = A[i] * A[i] + A[i])
2605 // o are used by a non binary operator or one which is not commutative
2606 // and associative (e.g., A[i] = A[i] % 3)
2607 // o might change the control flow (e.g., if (A[i]))
2608 // o are used in indirect memory accesses (e.g., A[B[i]])
2609 // o are used outside the current scop statement
2610 SmallPtrSet<const Instruction *, 8> InvalidLoads;
2611 SmallVector<BasicBlock *, 8> ScopBlocks;
2612 BasicBlock *BB = Stmt.getBasicBlock();
2613 if (BB)
2614 ScopBlocks.push_back(BB);
2615 else
2616 for (BasicBlock *Block : Stmt.getRegion()->blocks())
2617 ScopBlocks.push_back(Block);
2618 // Run the data flow analysis for all values in the scop statement
2619 for (BasicBlock *Block : ScopBlocks) {
2620 for (Instruction &Inst : *Block) {
2621 if ((Stmt.getParent())->getStmtFor(&Inst) != &Stmt)
2622 continue;
2623 bool UsedOutsideStmt = any_of(Inst.users(), [&Stmt](User *U) {
2624 return (Stmt.getParent())->getStmtFor(cast<Instruction>(U)) != &Stmt;
2625 });
2626 // Treat loads and stores special
2627 if (auto *Load = dyn_cast<LoadInst>(&Inst)) {
2628 // Invalidate all loads used which feed into the address of this load.
2629 if (auto *Ptr = dyn_cast<Instruction>(Load->getPointerOperand())) {
2630 const auto &It = State.find(Ptr);
2631 if (It != State.end())
2632 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2633 }
2634
2635 // If this load is used outside this stmt, invalidate it.
2636 if (UsedOutsideStmt)
2637 InvalidLoads.insert(Load);
2638
2639 // And indicate that this load uses itself once but without specifying
2640 // any reduction operator.
2641 State[Load].insert(
2642 std::make_pair(Load, std::make_pair(1, MemoryAccess::RT_BOTTOM)));
2643 continue;
2644 }
2645
2646 if (auto *Store = dyn_cast<StoreInst>(&Inst)) {
2647 // Invalidate all loads which feed into the address of this store.
2648 if (const Instruction *Ptr =
2649 dyn_cast<Instruction>(Store->getPointerOperand())) {
2650 const auto &It = State.find(Ptr);
2651 if (It != State.end())
2652 InvalidLoads.insert_range(llvm::make_first_range(It->second));
2653 }
2654
2655 // Propagate the uses of the value operand to the store
2656 if (auto *ValueInst = dyn_cast<Instruction>(Store->getValueOperand()))
2657 State.insert(std::make_pair(Store, State[ValueInst]));
2658 continue;
2659 }
2660
2661 // Non load and store instructions are either binary operators or they
2662 // will invalidate all used loads.
2663 auto *BinOp = dyn_cast<BinaryOperator>(&Inst);
2665 POLLY_DEBUG(dbgs() << "CurInst: " << Inst << " RT: " << CurRedType
2666 << "\n");
2667
2668 // Iterate over all operands and propagate their input loads to
2669 // instruction.
2670 FlowInSetTy &InstInFlowSet = State[&Inst];
2671 for (Use &Op : Inst.operands()) {
2672 auto *OpInst = dyn_cast<Instruction>(Op);
2673 if (!OpInst)
2674 continue;
2675
2676 POLLY_DEBUG(dbgs().indent(4) << "Op Inst: " << *OpInst << "\n");
2677 const StateTy::iterator &OpInFlowSetIt = State.find(OpInst);
2678 if (OpInFlowSetIt == State.end())
2679 continue;
2680
2681 // Iterate over all the input loads of the operand and combine them
2682 // with the input loads of current instruction.
2683 FlowInSetTy &OpInFlowSet = OpInFlowSetIt->second;
2684 for (auto &OpInFlowPair : OpInFlowSet) {
2685 unsigned OpFlowIn = OpInFlowPair.second.first;
2686 unsigned InstFlowIn = InstInFlowSet[OpInFlowPair.first].first;
2687
2688 MemoryAccess::ReductionType OpRedType = OpInFlowPair.second.second;
2689 MemoryAccess::ReductionType InstRedType =
2690 InstInFlowSet[OpInFlowPair.first].second;
2691
2692 MemoryAccess::ReductionType NewRedType =
2693 combineReductionType(OpRedType, CurRedType);
2694 if (InstFlowIn)
2695 NewRedType = combineReductionType(NewRedType, InstRedType);
2696
2697 POLLY_DEBUG(dbgs().indent(8) << "OpRedType: " << OpRedType << "\n");
2698 POLLY_DEBUG(dbgs().indent(8) << "NewRedType: " << NewRedType << "\n");
2699 InstInFlowSet[OpInFlowPair.first] =
2700 std::make_pair(OpFlowIn + InstFlowIn, NewRedType);
2701 }
2702 }
2703
2704 // If this operation is used outside the stmt, invalidate all the loads
2705 // which feed into it.
2706 if (UsedOutsideStmt)
2707 InvalidLoads.insert_range(llvm::make_first_range(InstInFlowSet));
2708 }
2709 }
2710
2711 // All used loads are propagated through the whole basic block; now try to
2712 // find valid reduction-like candidate pairs. These load-store pairs fulfill
2713 // all reduction like properties with regards to only this load-store chain.
2714 // We later have to check if the loaded value was invalidated by an
2715 // instruction not in that chain.
2716 using MemAccPair = std::pair<MemoryAccess *, MemoryAccess *>;
2717 DenseMap<MemAccPair, MemoryAccess::ReductionType> ValidCandidates;
2718
2719 // Iterate over all write memory accesses and check the loads flowing into
2720 // it for reduction candidate pairs.
2721 for (MemoryAccess *WriteMA : Stmt.MemAccs) {
2722 if (WriteMA->isRead())
2723 continue;
2724 StoreInst *St = dyn_cast<StoreInst>(WriteMA->getAccessInstruction());
2725 if (!St)
2726 continue;
2727 assert(!St->isVolatile());
2728
2729 FlowInSetTy &MaInFlowSet = State[WriteMA->getAccessInstruction()];
2730 for (auto &MaInFlowSetElem : MaInFlowSet) {
2731 MemoryAccess *ReadMA = &Stmt.getArrayAccessFor(MaInFlowSetElem.first);
2732 assert(ReadMA && "Couldn't find memory access for incoming load!");
2733
2734 POLLY_DEBUG(dbgs() << "'" << *ReadMA->getAccessInstruction()
2735 << "'\n\tflows into\n'"
2736 << *WriteMA->getAccessInstruction() << "'\n\t #"
2737 << MaInFlowSetElem.second.first << " times & RT: "
2738 << MaInFlowSetElem.second.second << "\n");
2739
2740 MemoryAccess::ReductionType RT = MaInFlowSetElem.second.second;
2741 unsigned NumAllowableInFlow = 1;
2742
2743 // We allow the load to flow in exactly once for binary reductions
2744 bool Valid = (MaInFlowSetElem.second.first == NumAllowableInFlow);
2745
2746 // Check if we saw a valid chain of binary operators.
2747 Valid = Valid && RT != MemoryAccess::RT_BOTTOM;
2748 Valid = Valid && RT != MemoryAccess::RT_NONE;
2749
2750 // Then check if the memory accesses allow a reduction.
2751 Valid = Valid && checkCandidatePairAccesses(
2752 ReadMA, WriteMA, Stmt.getDomain(), Stmt.MemAccs);
2753
2754 // Finally, mark the pair as a candidate or the load as a invalid one.
2755 if (Valid)
2756 ValidCandidates[std::make_pair(ReadMA, WriteMA)] = RT;
2757 else
2758 InvalidLoads.insert(ReadMA->getAccessInstruction());
2759 }
2760 }
2761
2762 // In the last step mark the memory accesses of candidate pairs as reduction
2763 // like if the load wasn't marked invalid in the previous step.
2764 for (auto &CandidatePair : ValidCandidates) {
2765 MemoryAccess *LoadMA = CandidatePair.first.first;
2766 if (InvalidLoads.count(LoadMA->getAccessInstruction()))
2767 continue;
2769 dbgs() << " Load :: "
2770 << *((CandidatePair.first.first)->getAccessInstruction())
2771 << "\n Store :: "
2772 << *((CandidatePair.first.second)->getAccessInstruction())
2773 << "\n are marked as reduction like\n");
2774 MemoryAccess::ReductionType RT = CandidatePair.second;
2775 CandidatePair.first.first->markAsReductionLike(RT);
2776 CandidatePair.first.second->markAsReductionLike(RT);
2777 }
2778}
2779
2781 auto &RIL = scop->getRequiredInvariantLoads();
2782 for (LoadInst *LI : RIL) {
2783 assert(LI && scop->contains(LI));
2784 // If there exists a statement in the scop which has a memory access for
2785 // @p LI, then mark this scop as infeasible for optimization.
2786 for (ScopStmt &Stmt : *scop)
2787 if (Stmt.getArrayAccessOrNULLFor(LI)) {
2788 scop->invalidate(INVARIANTLOAD, LI->getDebugLoc(), LI->getParent());
2789 return;
2790 }
2791 }
2792}
2793
2796 return;
2797
2798 isl::union_map Writes = scop->getWrites();
2799 for (ScopStmt &Stmt : *scop) {
2800 InvariantAccessesTy InvariantAccesses;
2801
2802 for (MemoryAccess *Access : Stmt) {
2803 isl::set NHCtx = getNonHoistableCtx(Access, Writes);
2804 if (!NHCtx.is_null())
2805 InvariantAccesses.push_back({Access, NHCtx});
2806 }
2807
2808 // Transfer the memory access from the statement to the SCoP.
2809 for (auto InvMA : InvariantAccesses)
2810 Stmt.removeMemoryAccess(InvMA.MA);
2811 addInvariantLoads(Stmt, InvariantAccesses);
2812 }
2813}
2814
2815/// Check if an access range is too complex.
2816///
2817/// An access range is too complex, if it contains either many disjuncts or
2818/// very complex expressions. As a simple heuristic, we assume if a set to
2819/// be too complex if the sum of existentially quantified dimensions and
2820/// set dimensions is larger than a threshold. This reliably detects both
2821/// sets with many disjuncts as well as sets with many divisions as they
2822/// arise in h264.
2823///
2824/// @param AccessRange The range to check for complexity.
2825///
2826/// @returns True if the access range is too complex.
2827static bool isAccessRangeTooComplex(isl::set AccessRange) {
2828 unsigned NumTotalDims = 0;
2829
2830 for (isl::basic_set BSet : AccessRange.get_basic_set_list()) {
2831 NumTotalDims += unsignedFromIslSize(BSet.dim(isl::dim::div));
2832 NumTotalDims += unsignedFromIslSize(BSet.dim(isl::dim::set));
2833 }
2834
2835 if (NumTotalDims > MaxDimensionsInAccessRange)
2836 return true;
2837
2838 return false;
2839}
2840
2842 isl::union_map Writes) {
2843 if (auto *BasePtrMA = scop->lookupBasePtrAccess(MA)) {
2844 return getNonHoistableCtx(BasePtrMA, Writes).is_null();
2845 }
2846
2847 Value *BaseAddr = MA->getOriginalBaseAddr();
2848 if (auto *BasePtrInst = dyn_cast<Instruction>(BaseAddr))
2849 if (!isa<LoadInst>(BasePtrInst))
2850 return scop->contains(BasePtrInst);
2851
2852 return false;
2853}
2854
2856 if (UserContextStr.empty())
2857 return;
2858
2859 isl::set UserContext = isl::set(scop->getIslCtx(), UserContextStr.c_str());
2860 isl::space Space = scop->getParamSpace();
2861 isl::size SpaceParams = Space.dim(isl::dim::param);
2862 if (unsignedFromIslSize(SpaceParams) !=
2863 unsignedFromIslSize(UserContext.dim(isl::dim::param))) {
2864 std::string SpaceStr = stringFromIslObj(Space, "null");
2865 errs() << "Error: the context provided in -polly-context has not the same "
2866 << "number of dimensions than the computed context. Due to this "
2867 << "mismatch, the -polly-context option is ignored. Please provide "
2868 << "the context in the parameter space: " << SpaceStr << ".\n";
2869 return;
2870 }
2871
2872 for (auto i : rangeIslSize(0, SpaceParams)) {
2873 std::string NameContext =
2874 scop->getContext().get_dim_name(isl::dim::param, i);
2875 std::string NameUserContext = UserContext.get_dim_name(isl::dim::param, i);
2876
2877 if (NameContext != NameUserContext) {
2878 std::string SpaceStr = stringFromIslObj(Space, "null");
2879 errs() << "Error: the name of dimension " << i
2880 << " provided in -polly-context "
2881 << "is '" << NameUserContext << "', but the name in the computed "
2882 << "context is '" << NameContext
2883 << "'. Due to this name mismatch, "
2884 << "the -polly-context option is ignored. Please provide "
2885 << "the context in the parameter space: " << SpaceStr << ".\n";
2886 return;
2887 }
2888
2889 UserContext = UserContext.set_dim_id(isl::dim::param, i,
2890 Space.get_dim_id(isl::dim::param, i));
2891 }
2892 isl::set newContext = scop->getContext().intersect(UserContext);
2893 scop->setContext(newContext);
2894}
2895
2897 isl::union_map Writes) {
2898 // TODO: Loads that are not loop carried, hence are in a statement with
2899 // zero iterators, are by construction invariant, though we
2900 // currently "hoist" them anyway. This is necessary because we allow
2901 // them to be treated as parameters (e.g., in conditions) and our code
2902 // generation would otherwise use the old value.
2903
2904 auto &Stmt = *Access->getStatement();
2905 BasicBlock *BB = Stmt.getEntryBlock();
2906
2907 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine() ||
2908 Access->isMemoryIntrinsic())
2909 return {};
2910
2911 // Skip accesses that have an invariant base pointer which is defined but
2912 // not loaded inside the SCoP. This can happened e.g., if a readnone call
2913 // returns a pointer that is used as a base address. However, as we want
2914 // to hoist indirect pointers, we allow the base pointer to be defined in
2915 // the region if it is also a memory access. Each ScopArrayInfo object
2916 // that has a base pointer origin has a base pointer that is loaded and
2917 // that it is invariant, thus it will be hoisted too. However, if there is
2918 // no base pointer origin we check that the base pointer is defined
2919 // outside the region.
2920 auto *LI = cast<LoadInst>(Access->getAccessInstruction());
2921 if (hasNonHoistableBasePtrInScop(Access, Writes))
2922 return {};
2923
2924 isl::map AccessRelation = Access->getAccessRelation();
2925 assert(!AccessRelation.is_empty());
2926
2927 if (AccessRelation.involves_dims(isl::dim::in, 0, Stmt.getNumIterators()))
2928 return {};
2929
2930 AccessRelation = AccessRelation.intersect_domain(Stmt.getDomain());
2931 isl::set SafeToLoad;
2932
2933 auto &DL = scop->getFunction().getDataLayout();
2934 if (isSafeToLoadUnconditionally(LI->getPointerOperand(), LI->getType(),
2935 LI->getAlign(), DL, nullptr)) {
2936 SafeToLoad = isl::set::universe(AccessRelation.get_space().range());
2937 } else if (BB != LI->getParent()) {
2938 // Skip accesses in non-affine subregions as they might not be executed
2939 // under the same condition as the entry of the non-affine subregion.
2940 return {};
2941 } else {
2942 SafeToLoad = AccessRelation.range();
2943 }
2944
2945 if (isAccessRangeTooComplex(AccessRelation.range()))
2946 return {};
2947
2948 isl::union_map Written = Writes.intersect_range(SafeToLoad);
2949 isl::set WrittenCtx = Written.params();
2950 bool IsWritten = !WrittenCtx.is_empty();
2951
2952 if (!IsWritten)
2953 return WrittenCtx;
2954
2955 WrittenCtx = WrittenCtx.remove_divs();
2956 bool TooComplex =
2958 if (TooComplex || !isRequiredInvariantLoad(LI))
2959 return {};
2960
2961 scop->addAssumption(INVARIANTLOAD, WrittenCtx, LI->getDebugLoc(),
2962 AS_RESTRICTION, LI->getParent());
2963 return WrittenCtx;
2964}
2965
2966static bool isAParameter(llvm::Value *maybeParam, const Function &F) {
2967 for (const llvm::Argument &Arg : F.args())
2968 if (&Arg == maybeParam)
2969 return true;
2970
2971 return false;
2972}
2973
2975 bool StmtInvalidCtxIsEmpty,
2976 bool MAInvalidCtxIsEmpty,
2977 bool NonHoistableCtxIsEmpty) {
2978 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
2979 const DataLayout &DL = LInst->getDataLayout();
2981 isAParameter(LInst->getPointerOperand(), scop->getFunction()))
2982 return true;
2983
2984 // TODO: We can provide more information for better but more expensive
2985 // results.
2986 if (!isDereferenceableAndAlignedPointer(
2987 LInst->getPointerOperand(), LInst->getType(), LInst->getAlign(), DL))
2988 return false;
2989
2990 // If the location might be overwritten we do not hoist it unconditionally.
2991 //
2992 // TODO: This is probably too conservative.
2993 if (!NonHoistableCtxIsEmpty)
2994 return false;
2995
2996 // If a dereferenceable load is in a statement that is modeled precisely we
2997 // can hoist it.
2998 if (StmtInvalidCtxIsEmpty && MAInvalidCtxIsEmpty)
2999 return true;
3000
3001 // Even if the statement is not modeled precisely we can hoist the load if it
3002 // does not involve any parameters that might have been specialized by the
3003 // statement domain.
3004 for (const SCEV *Subscript : MA->subscripts())
3005 if (!isa<SCEVConstant>(Subscript))
3006 return false;
3007 return true;
3008}
3009
3011 InvariantAccessesTy &InvMAs) {
3012 if (InvMAs.empty())
3013 return;
3014
3015 isl::set StmtInvalidCtx = Stmt.getInvalidContext();
3016 bool StmtInvalidCtxIsEmpty = StmtInvalidCtx.is_empty();
3017
3018 // Get the context under which the statement is executed but remove the error
3019 // context under which this statement is reached.
3020 isl::set DomainCtx = Stmt.getDomain().params();
3021 DomainCtx = DomainCtx.subtract(StmtInvalidCtx);
3022
3024 auto *AccInst = InvMAs.front().MA->getAccessInstruction();
3025 scop->invalidate(COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent());
3026 return;
3027 }
3028
3029 // Project out all parameters that relate to loads in the statement. Otherwise
3030 // we could have cyclic dependences on the constraints under which the
3031 // hoisted loads are executed and we could not determine an order in which to
3032 // pre-load them. This happens because not only lower bounds are part of the
3033 // domain but also upper bounds.
3034 for (auto &InvMA : InvMAs) {
3035 auto *MA = InvMA.MA;
3036 Instruction *AccInst = MA->getAccessInstruction();
3037 if (SE.isSCEVable(AccInst->getType())) {
3038 SetVector<Value *> Values;
3039 for (const SCEV *Parameter : scop->parameters()) {
3040 Values.clear();
3041 findValues(Parameter, SE, Values);
3042 if (!Values.count(AccInst))
3043 continue;
3044
3045 isl::id ParamId = scop->getIdForParam(Parameter);
3046 if (!ParamId.is_null()) {
3047 int Dim = DomainCtx.find_dim_by_id(isl::dim::param, ParamId);
3048 if (Dim >= 0)
3049 DomainCtx = DomainCtx.eliminate(isl::dim::param, Dim, 1);
3050 }
3051 }
3052 }
3053 }
3054
3055 for (auto &InvMA : InvMAs) {
3056 auto *MA = InvMA.MA;
3057 isl::set NHCtx = InvMA.NonHoistableCtx;
3058
3059 // Check for another invariant access that accesses the same location as
3060 // MA and if found consolidate them. Otherwise create a new equivalence
3061 // class at the end of InvariantEquivClasses.
3062 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
3063 Type *Ty = LInst->getType();
3064 const SCEV *PointerSCEV = SE.getSCEV(LInst->getPointerOperand());
3065
3066 isl::set MAInvalidCtx = MA->getInvalidContext();
3067 bool NonHoistableCtxIsEmpty = NHCtx.is_empty();
3068 bool MAInvalidCtxIsEmpty = MAInvalidCtx.is_empty();
3069
3070 isl::set MACtx;
3071 // Check if we know that this pointer can be speculatively accessed.
3072 if (canAlwaysBeHoisted(MA, StmtInvalidCtxIsEmpty, MAInvalidCtxIsEmpty,
3073 NonHoistableCtxIsEmpty)) {
3074 MACtx = isl::set::universe(DomainCtx.get_space());
3075 } else {
3076 MACtx = DomainCtx;
3077 MACtx = MACtx.subtract(MAInvalidCtx.unite(NHCtx));
3078 MACtx = MACtx.gist_params(scop->getContext());
3079 }
3080
3081 bool Consolidated = false;
3082 for (auto &IAClass : scop->invariantEquivClasses()) {
3083 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
3084 continue;
3085
3086 // If the pointer and the type is equal check if the access function wrt.
3087 // to the domain is equal too. It can happen that the domain fixes
3088 // parameter values and these can be different for distinct part of the
3089 // SCoP. If this happens we cannot consolidate the loads but need to
3090 // create a new invariant load equivalence class.
3091 auto &MAs = IAClass.InvariantAccesses;
3092 if (!MAs.empty()) {
3093 auto *LastMA = MAs.front();
3094
3095 isl::set AR = MA->getAccessRelation().range();
3096 isl::set LastAR = LastMA->getAccessRelation().range();
3097 bool SameAR = AR.is_equal(LastAR);
3098
3099 if (!SameAR)
3100 continue;
3101 }
3102
3103 // Add MA to the list of accesses that are in this class.
3104 MAs.push_front(MA);
3105
3106 Consolidated = true;
3107
3108 // Unify the execution context of the class and this statement.
3109 isl::set IAClassDomainCtx = IAClass.ExecutionContext;
3110 if (!IAClassDomainCtx.is_null())
3111 IAClassDomainCtx = IAClassDomainCtx.unite(MACtx).coalesce();
3112 else
3113 IAClassDomainCtx = MACtx;
3114 IAClass.ExecutionContext = IAClassDomainCtx;
3115 break;
3116 }
3117
3118 if (Consolidated)
3119 continue;
3120
3121 MACtx = MACtx.coalesce();
3122
3123 // If we did not consolidate MA, thus did not find an equivalence class
3124 // for it, we create a new one.
3125 scop->addInvariantEquivClass(
3126 InvariantEquivClassTy{PointerSCEV, MemoryAccessList{MA}, MACtx, Ty});
3127 }
3128}
3129
3130/// Find the canonical scop array info object for a set of invariant load
3131/// hoisted loads. The canonical array is the one that corresponds to the
3132/// first load in the list of accesses which is used as base pointer of a
3133/// scop array.
3135 MemoryAccessList &Accesses) {
3136 for (MemoryAccess *Access : Accesses) {
3137 const ScopArrayInfo *CanonicalArray = S.getScopArrayInfoOrNull(
3138 Access->getAccessInstruction(), MemoryKind::Array);
3139 if (CanonicalArray)
3140 return CanonicalArray;
3141 }
3142 return nullptr;
3143}
3144
3145/// Check if @p Array severs as base array in an invariant load.
3147 for (InvariantEquivClassTy &EqClass2 : S.getInvariantAccesses())
3148 for (MemoryAccess *Access2 : EqClass2.InvariantAccesses)
3149 if (Access2->getScopArrayInfo() == Array)
3150 return true;
3151 return false;
3152}
3153
3154/// Replace the base pointer arrays in all memory accesses referencing @p Old,
3155/// with a reference to @p New.
3156static void replaceBasePtrArrays(Scop &S, const ScopArrayInfo *Old,
3157 const ScopArrayInfo *New) {
3158 for (ScopStmt &Stmt : S)
3159 for (MemoryAccess *Access : Stmt) {
3160 if (Access->getLatestScopArrayInfo() != Old)
3161 continue;
3162
3163 isl::id Id = New->getBasePtrId();
3164 isl::map Map = Access->getAccessRelation();
3165 Map = Map.set_tuple_id(isl::dim::out, Id);
3166 Access->setAccessRelation(Map);
3167 }
3168}
3169
3171 for (InvariantEquivClassTy &EqClass : scop->InvariantEquivClasses) {
3172 MemoryAccessList &BasePtrAccesses = EqClass.InvariantAccesses;
3173
3174 const ScopArrayInfo *CanonicalBasePtrSAI =
3175 findCanonicalArray(*scop, BasePtrAccesses);
3176
3177 if (!CanonicalBasePtrSAI)
3178 continue;
3179
3180 for (MemoryAccess *BasePtrAccess : BasePtrAccesses) {
3181 const ScopArrayInfo *BasePtrSAI = scop->getScopArrayInfoOrNull(
3182 BasePtrAccess->getAccessInstruction(), MemoryKind::Array);
3183 if (!BasePtrSAI || BasePtrSAI == CanonicalBasePtrSAI ||
3184 !BasePtrSAI->isCompatibleWith(CanonicalBasePtrSAI))
3185 continue;
3186
3187 // we currently do not canonicalize arrays where some accesses are
3188 // hoisted as invariant loads. If we would, we need to update the access
3189 // function of the invariant loads as well. However, as this is not a
3190 // very common situation, we leave this for now to avoid further
3191 // complexity increases.
3192 if (isUsedForIndirectHoistedLoad(*scop, BasePtrSAI))
3193 continue;
3194
3195 replaceBasePtrArrays(*scop, BasePtrSAI, CanonicalBasePtrSAI);
3196 }
3197 }
3198}
3199
3201 for (MemoryAccess *Access : Stmt.MemAccs) {
3202 Type *ElementType = Access->getElementType();
3203
3204 MemoryKind Ty;
3205 if (Access->isPHIKind())
3206 Ty = MemoryKind::PHI;
3207 else if (Access->isExitPHIKind())
3209 else if (Access->isValueKind())
3210 Ty = MemoryKind::Value;
3211 else
3212 Ty = MemoryKind::Array;
3213
3214 // Create isl::pw_aff for SCEVs which describe sizes. Collect all
3215 // assumptions which are taken. isl::pw_aff objects are cached internally
3216 // and they are used later by scop.
3217 for (const SCEV *Size : Access->Sizes) {
3218 if (!Size)
3219 continue;
3220 scop->getPwAff(Size, nullptr, false, &RecordedAssumptions);
3221 }
3222 auto *SAI = scop->getOrCreateScopArrayInfo(Access->getOriginalBaseAddr(),
3223 ElementType, Access->Sizes, Ty);
3224
3225 // Create isl::pw_aff for SCEVs which describe subscripts. Collect all
3226 // assumptions which are taken. isl::pw_aff objects are cached internally
3227 // and they are used later by scop.
3228 for (const SCEV *Subscript : Access->subscripts()) {
3229 if (!Access->isAffine() || !Subscript)
3230 continue;
3231 scop->getPwAff(Subscript, Stmt.getEntryBlock(), false,
3233 }
3234 Access->buildAccessRelation(SAI);
3235 scop->addAccessData(Access);
3236 }
3237}
3238
3239/// Add the minimal/maximal access in @p Set to @p User.
3240///
3241/// @return True if more accesses should be added, false if we reached the
3242/// maximal number of run-time checks to be generated.
3244 Scop::MinMaxVectorTy &MinMaxAccesses, Scop &S) {
3245 isl::pw_multi_aff MinPMA, MaxPMA;
3246 isl::pw_aff LastDimAff;
3247 isl::aff OneAff;
3248 unsigned Pos;
3249
3250 Set = Set.remove_divs();
3251 polly::simplify(Set);
3252
3254 Set = Set.simple_hull();
3255
3256 // Restrict the number of parameters involved in the access as the lexmin/
3257 // lexmax computation will take too long if this number is high.
3258 //
3259 // Experiments with a simple test case using an i7 4800MQ:
3260 //
3261 // #Parameters involved | Time (in sec)
3262 // 6 | 0.01
3263 // 7 | 0.04
3264 // 8 | 0.12
3265 // 9 | 0.40
3266 // 10 | 1.54
3267 // 11 | 6.78
3268 // 12 | 30.38
3269 //
3270 if (isl_set_n_param(Set.get()) >
3271 static_cast<isl_size>(RunTimeChecksMaxParameters)) {
3272 unsigned InvolvedParams = 0;
3273 for (unsigned u = 0, e = isl_set_n_param(Set.get()); u < e; u++)
3274 if (Set.involves_dims(isl::dim::param, u, 1))
3275 InvolvedParams++;
3276
3277 if (InvolvedParams > RunTimeChecksMaxParameters)
3278 return false;
3279 }
3280
3281 MinPMA = Set.lexmin_pw_multi_aff();
3282 MaxPMA = Set.lexmax_pw_multi_aff();
3283
3284 MinPMA = MinPMA.coalesce();
3285 MaxPMA = MaxPMA.coalesce();
3286
3287 if (MaxPMA.is_null())
3288 return false;
3289
3290 unsigned MaxOutputSize = unsignedFromIslSize(MaxPMA.dim(isl::dim::out));
3291
3292 // Adjust the last dimension of the maximal access by one as we want to
3293 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer
3294 // we test during code generation might now point after the end of the
3295 // allocated array but we will never dereference it anyway.
3296 assert(MaxOutputSize >= 1 && "Assumed at least one output dimension");
3297
3298 Pos = MaxOutputSize - 1;
3299 LastDimAff = MaxPMA.at(Pos);
3300 OneAff = isl::aff(isl::local_space(LastDimAff.get_domain_space()));
3301 OneAff = OneAff.add_constant_si(1);
3302 LastDimAff = LastDimAff.add(OneAff);
3303 MaxPMA = MaxPMA.set_pw_aff(Pos, LastDimAff);
3304
3305 if (MinPMA.is_null() || MaxPMA.is_null())
3306 return false;
3307
3308 MinMaxAccesses.push_back(std::make_pair(MinPMA, MaxPMA));
3309
3310 return true;
3311}
3312
3313/// Wrapper function to calculate minimal/maximal accesses to each array.
3315 Scop::MinMaxVectorTy &MinMaxAccesses) {
3316 MinMaxAccesses.reserve(AliasGroup.size());
3317
3318 isl::union_set Domains = scop->getDomains();
3319 isl::union_map Accesses = isl::union_map::empty(scop->getIslCtx());
3320
3321 for (MemoryAccess *MA : AliasGroup)
3322 Accesses = Accesses.unite(MA->getAccessRelation());
3323
3324 Accesses = Accesses.intersect_domain(Domains);
3325 isl::union_set Locations = Accesses.range();
3326
3327 bool LimitReached = false;
3328 for (isl::set Set : Locations.get_set_list()) {
3329 LimitReached |= !buildMinMaxAccess(Set, MinMaxAccesses, *scop);
3330 if (LimitReached)
3331 break;
3332 }
3333
3334 return !LimitReached;
3335}
3336
3339 Domain = Domain.project_out(isl::dim::set, 0,
3340 unsignedFromIslSize(Domain.tuple_dim()));
3341 return Domain.reset_tuple_id();
3342}
3343
3346 return true;
3347
3348 if (buildAliasGroups()) {
3349 // Aliasing assumptions do not go through addAssumption but we still want to
3350 // collect statistics so we do it here explicitly.
3351 if (scop->getAliasGroups().size())
3353 return true;
3354 }
3355
3356 // If a problem occurs while building the alias groups we need to delete
3357 // this SCoP and pretend it wasn't valid in the first place. To this end
3358 // we make the assumed context infeasible.
3359 scop->invalidate(ALIASING, DebugLoc());
3360
3361 POLLY_DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << scop->getNameStr()
3362 << " could not be created. This SCoP has been dismissed.");
3363 return false;
3364}
3365
3366std::tuple<ScopBuilder::AliasGroupVectorTy, DenseSet<const ScopArrayInfo *>>
3368 BatchAAResults BAA(AA);
3369 AliasSetTracker AST(BAA);
3370
3371 DenseMap<Value *, MemoryAccess *> PtrToAcc;
3372 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3373 for (ScopStmt &Stmt : *scop) {
3374
3375 isl::set StmtDomain = Stmt.getDomain();
3376 bool StmtDomainEmpty = StmtDomain.is_empty();
3377
3378 // Statements with an empty domain will never be executed.
3379 if (StmtDomainEmpty)
3380 continue;
3381
3382 for (MemoryAccess *MA : Stmt) {
3383 if (MA->isScalarKind())
3384 continue;
3385 if (!MA->isRead())
3386 HasWriteAccess.insert(MA->getScopArrayInfo());
3387 MemAccInst Acc(MA->getAccessInstruction());
3388 if (MA->isRead() && isa<MemTransferInst>(Acc))
3389 PtrToAcc[cast<MemTransferInst>(Acc)->getRawSource()] = MA;
3390 else
3391 PtrToAcc[Acc.getPointerOperand()] = MA;
3392 AST.add(Acc);
3393 }
3394 }
3395
3396 AliasGroupVectorTy AliasGroups;
3397 for (AliasSet &AS : AST) {
3398 if (AS.isMustAlias() || AS.isForwardingAliasSet())
3399 continue;
3400 AliasGroupTy AG;
3401 for (const Value *Ptr : AS.getPointers())
3402 AG.push_back(PtrToAcc[const_cast<Value *>(Ptr)]);
3403 if (AG.size() < 2)
3404 continue;
3405 AliasGroups.push_back(std::move(AG));
3406 }
3407
3408 return std::make_tuple(AliasGroups, HasWriteAccess);
3409}
3410
3412 // To create sound alias checks we perform the following steps:
3413 // o) We partition each group into read only and non read only accesses.
3414 // o) For each group with more than one base pointer we then compute minimal
3415 // and maximal accesses to each array of a group in read only and non
3416 // read only partitions separately.
3417 AliasGroupVectorTy AliasGroups;
3418 DenseSet<const ScopArrayInfo *> HasWriteAccess;
3419
3420 std::tie(AliasGroups, HasWriteAccess) = buildAliasGroupsForAccesses();
3421
3422 splitAliasGroupsByDomain(AliasGroups);
3423
3424 for (AliasGroupTy &AG : AliasGroups) {
3425 if (!scop->hasFeasibleRuntimeContext())
3426 return false;
3427
3428 {
3429 IslMaxOperationsGuard MaxOpGuard(scop->getIslCtx().get(), OptComputeOut);
3430 bool Valid = buildAliasGroup(AG, HasWriteAccess);
3431 if (!Valid)
3432 return false;
3433 }
3434 if (isl_ctx_last_error(scop->getIslCtx().get()) == isl_error_quota) {
3435 scop->invalidate(COMPLEXITY, DebugLoc());
3436 return false;
3437 }
3438 }
3439
3440 return true;
3441}
3442
3444 AliasGroupTy &AliasGroup, DenseSet<const ScopArrayInfo *> HasWriteAccess) {
3445 AliasGroupTy ReadOnlyAccesses;
3446 AliasGroupTy ReadWriteAccesses;
3447 SmallPtrSet<const ScopArrayInfo *, 4> ReadWriteArrays;
3448 SmallPtrSet<const ScopArrayInfo *, 4> ReadOnlyArrays;
3449
3450 if (AliasGroup.size() < 2)
3451 return true;
3452
3453 for (MemoryAccess *Access : AliasGroup) {
3454 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "PossibleAlias",
3455 Access->getAccessInstruction())
3456 << "Possibly aliasing pointer, use restrict keyword.");
3457 const ScopArrayInfo *Array = Access->getScopArrayInfo();
3458 if (HasWriteAccess.count(Array)) {
3459 ReadWriteArrays.insert(Array);
3460 ReadWriteAccesses.push_back(Access);
3461 } else {
3462 ReadOnlyArrays.insert(Array);
3463 ReadOnlyAccesses.push_back(Access);
3464 }
3465 }
3466
3467 // If there are no read-only pointers, and less than two read-write pointers,
3468 // no alias check is needed.
3469 if (ReadOnlyAccesses.empty() && ReadWriteArrays.size() <= 1)
3470 return true;
3471
3472 // If there is no read-write pointer, no alias check is needed.
3473 if (ReadWriteArrays.empty())
3474 return true;
3475
3476 // For non-affine accesses, no alias check can be generated as we cannot
3477 // compute a sufficiently tight lower and upper bound: bail out.
3478 for (MemoryAccess *MA : AliasGroup) {
3479 if (!MA->isAffine()) {
3480 scop->invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc(),
3481 MA->getAccessInstruction()->getParent());
3482 return false;
3483 }
3484 }
3485
3486 // Ensure that for all memory accesses for which we generate alias checks,
3487 // their base pointers are available.
3488 for (MemoryAccess *MA : AliasGroup) {
3489 if (MemoryAccess *BasePtrMA = scop->lookupBasePtrAccess(MA))
3490 scop->addRequiredInvariantLoad(
3491 cast<LoadInst>(BasePtrMA->getAccessInstruction()));
3492 }
3493
3494 // scop->getAliasGroups().emplace_back();
3495 // Scop::MinMaxVectorPairTy &pair = scop->getAliasGroups().back();
3496 Scop::MinMaxVectorTy MinMaxAccessesReadWrite;
3497 Scop::MinMaxVectorTy MinMaxAccessesReadOnly;
3498
3499 bool Valid;
3500
3501 Valid = calculateMinMaxAccess(ReadWriteAccesses, MinMaxAccessesReadWrite);
3502
3503 if (!Valid)
3504 return false;
3505
3506 // Bail out if the number of values we need to compare is too large.
3507 // This is important as the number of comparisons grows quadratically with
3508 // the number of values we need to compare.
3509 if (MinMaxAccessesReadWrite.size() + ReadOnlyArrays.size() >
3511 return false;
3512
3513 Valid = calculateMinMaxAccess(ReadOnlyAccesses, MinMaxAccessesReadOnly);
3514
3515 scop->addAliasGroup(MinMaxAccessesReadWrite, MinMaxAccessesReadOnly);
3516 if (!Valid)
3517 return false;
3518
3519 return true;
3520}
3521
3523 for (unsigned u = 0; u < AliasGroups.size(); u++) {
3524 AliasGroupTy NewAG;
3525 AliasGroupTy &AG = AliasGroups[u];
3526 AliasGroupTy::iterator AGI = AG.begin();
3527 isl::set AGDomain = getAccessDomain(*AGI);
3528 while (AGI != AG.end()) {
3529 MemoryAccess *MA = *AGI;
3530 isl::set MADomain = getAccessDomain(MA);
3531 if (AGDomain.is_disjoint(MADomain)) {
3532 NewAG.push_back(MA);
3533 AGI = AG.erase(AGI);
3534 } else {
3535 AGDomain = AGDomain.unite(MADomain);
3536 AGI++;
3537 }
3538 }
3539 if (NewAG.size() > 1)
3540 AliasGroups.push_back(std::move(NewAG));
3541 }
3542}
3543
3544#ifndef NDEBUG
3545static void verifyUse(Scop *S, Use &Op, LoopInfo &LI) {
3546 auto PhysUse = VirtualUse::create(S, Op, &LI, false);
3547 auto VirtUse = VirtualUse::create(S, Op, &LI, true);
3548 assert(PhysUse.getKind() == VirtUse.getKind());
3549}
3550
3551/// Check the consistency of every statement's MemoryAccesses.
3552///
3553/// The check is carried out by expecting the "physical" kind of use (derived
3554/// from the BasicBlocks instructions resides in) to be same as the "virtual"
3555/// kind of use (derived from a statement's MemoryAccess).
3556///
3557/// The "physical" uses are taken by ensureValueRead to determine whether to
3558/// create MemoryAccesses. When done, the kind of scalar access should be the
3559/// same no matter which way it was derived.
3560///
3561/// The MemoryAccesses might be changed by later SCoP-modifying passes and hence
3562/// can intentionally influence on the kind of uses (not corresponding to the
3563/// "physical" anymore, hence called "virtual"). The CodeGenerator therefore has
3564/// to pick up the virtual uses. But here in the code generator, this has not
3565/// happened yet, such that virtual and physical uses are equivalent.
3566static void verifyUses(Scop *S, LoopInfo &LI, DominatorTree &DT) {
3567 for (auto *BB : S->getRegion().blocks()) {
3568 for (auto &Inst : *BB) {
3569 auto *Stmt = S->getStmtFor(&Inst);
3570 if (!Stmt)
3571 continue;
3572
3573 if (isIgnoredIntrinsic(&Inst))
3574 continue;
3575
3576 // Branch conditions are encoded in the statement domains.
3577 if (Inst.isTerminator() && Stmt->isBlockStmt())
3578 continue;
3579
3580 // Verify all uses.
3581 for (auto &Op : Inst.operands())
3582 verifyUse(S, Op, LI);
3583
3584 // Stores do not produce values used by other statements.
3585 if (isa<StoreInst>(Inst))
3586 continue;
3587
3588 // For every value defined in the block, also check that a use of that
3589 // value in the same statement would not be an inter-statement use. It can
3590 // still be synthesizable or load-hoisted, but these kind of instructions
3591 // are not directly copied in code-generation.
3592 auto VirtDef =
3593 VirtualUse::create(S, Stmt, Stmt->getSurroundingLoop(), &Inst, true);
3594 assert(VirtDef.getKind() == VirtualUse::Synthesizable ||
3595 VirtDef.getKind() == VirtualUse::Intra ||
3596 VirtDef.getKind() == VirtualUse::Hoisted);
3597 }
3598 }
3599
3600 if (S->hasSingleExitEdge())
3601 return;
3602
3603 // PHINodes in the SCoP region's exit block are also uses to be checked.
3604 if (!S->getRegion().isTopLevelRegion()) {
3605 for (auto &Inst : *S->getRegion().getExit()) {
3606 if (!isa<PHINode>(Inst))
3607 break;
3608
3609 for (auto &Op : Inst.operands())
3610 verifyUse(S, Op, LI);
3611 }
3612 }
3613}
3614#endif
3615
3616void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) {
3617 scop.reset(new Scop(R, SE, LI, DT, *SD.getDetectionContext(&R), ORE,
3618 SD.getNextID()));
3619
3620 buildStmts(R);
3621
3622 // Create all invariant load instructions first. These are categorized as
3623 // 'synthesizable', therefore are not part of any ScopStmt but need to be
3624 // created somewhere.
3625 const InvariantLoadsSetTy &RIL = scop->getRequiredInvariantLoads();
3626 for (BasicBlock *BB : scop->getRegion().blocks()) {
3627 if (SD.isErrorBlock(*BB, scop->getRegion()))
3628 continue;
3629
3630 for (Instruction &Inst : *BB) {
3631 LoadInst *Load = dyn_cast<LoadInst>(&Inst);
3632 if (!Load)
3633 continue;
3634
3635 if (!RIL.count(Load))
3636 continue;
3637
3638 // Invariant loads require a MemoryAccess to be created in some statement.
3639 // It is not important to which statement the MemoryAccess is added
3640 // because it will later be removed from the ScopStmt again. We chose the
3641 // first statement of the basic block the LoadInst is in.
3642 ArrayRef<ScopStmt *> List = scop->getStmtListFor(BB);
3643 assert(!List.empty());
3644 ScopStmt *RILStmt = List.front();
3645 buildMemoryAccess(Load, RILStmt);
3646 }
3647 }
3649
3650 // In case the region does not have an exiting block we will later (during
3651 // code generation) split the exit block. This will move potential PHI nodes
3652 // from the current exit block into the new region exiting block. Hence, PHI
3653 // nodes that are at this point not part of the region will be.
3654 // To handle these PHI nodes later we will now model their operands as scalar
3655 // accesses. Note that we do not model anything in the exit block if we have
3656 // an exiting block in the region, as there will not be any splitting later.
3657 if (!R.isTopLevelRegion() && !scop->hasSingleExitEdge()) {
3658 for (Instruction &Inst : *R.getExit()) {
3659 PHINode *PHI = dyn_cast<PHINode>(&Inst);
3660 if (!PHI)
3661 break;
3662
3663 buildPHIAccesses(nullptr, PHI, nullptr, true);
3664 }
3665 }
3666
3667 // Create memory accesses for global reads since all arrays are now known.
3668 const SCEV *AF = SE.getConstant(IntegerType::getInt64Ty(SE.getContext()), 0);
3669 for (auto GlobalReadPair : GlobalReads) {
3670 ScopStmt *GlobalReadStmt = GlobalReadPair.first;
3671 Instruction *GlobalRead = GlobalReadPair.second;
3672 for (auto *BP : ArrayBasePointers)
3673 addArrayAccess(GlobalReadStmt, MemAccInst(GlobalRead), MemoryAccess::READ,
3674 BP, BP->getType(), false, {AF}, {nullptr}, GlobalRead);
3675 }
3676
3678
3679 /// A map from basic blocks to their invalid domains.
3680 DenseMap<BasicBlock *, isl::set> InvalidDomainMap;
3681
3682 if (!buildDomains(&R, InvalidDomainMap)) {
3684 dbgs() << "Bailing-out because buildDomains encountered problems\n");
3685 return;
3686 }
3687
3688 addUserAssumptions(AC, InvalidDomainMap);
3689
3690 // Initialize the invalid domain.
3691 for (ScopStmt &Stmt : scop->Stmts)
3692 if (Stmt.isBlockStmt())
3693 Stmt.setInvalidDomain(InvalidDomainMap[Stmt.getEntryBlock()]);
3694 else
3695 Stmt.setInvalidDomain(InvalidDomainMap[getRegionNodeBasicBlock(
3696 Stmt.getRegion()->getNode())]);
3697
3698 // Remove empty statements.
3699 // Exit early in case there are no executable statements left in this scop.
3700 scop->removeStmtNotInDomainMap();
3701 scop->simplifySCoP(false);
3702 if (scop->isEmpty()) {
3703 POLLY_DEBUG(dbgs() << "Bailing-out because SCoP is empty\n");
3704 return;
3705 }
3706
3707 // The ScopStmts now have enough information to initialize themselves.
3708 for (ScopStmt &Stmt : *scop) {
3710
3711 buildDomain(Stmt);
3713
3714 if (DetectReductions)
3715 checkForReductions(Stmt);
3716 }
3717
3718 // Check early for a feasible runtime context.
3719 if (!scop->hasFeasibleRuntimeContext()) {
3721 dbgs() << "Bailing-out because of unfeasible context (early)\n");
3722 return;
3723 }
3724
3725 // Check early for profitability. Afterwards it cannot change anymore,
3726 // only the runtime context could become infeasible.
3727 if (!scop->isProfitable(UnprofitableScalarAccs)) {
3728 scop->invalidate(PROFITABLE, DebugLoc());
3730 dbgs() << "Bailing-out because SCoP is not considered profitable\n");
3731 return;
3732 }
3733
3734 buildSchedule();
3735
3737
3738 scop->realignParams();
3740
3741 // After the context was fully constructed, thus all our knowledge about
3742 // the parameters is in there, we add all recorded assumptions to the
3743 // assumed/invalid context.
3745
3746 scop->simplifyContexts();
3747 if (!buildAliasChecks()) {
3748 POLLY_DEBUG(dbgs() << "Bailing-out because could not build alias checks\n");
3749 return;
3750 }
3751
3755 scop->simplifySCoP(true);
3756
3757 // Check late for a feasible runtime context because profitability did not
3758 // change.
3759 if (!scop->hasFeasibleRuntimeContext()) {
3760 POLLY_DEBUG(dbgs() << "Bailing-out because of unfeasible context (late)\n");
3761 return;
3762 }
3763
3764#ifndef NDEBUG
3765 verifyUses(scop.get(), LI, DT);
3766#endif
3767}
3768
3769ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AAResults &AA,
3770 const DataLayout &DL, DominatorTree &DT, LoopInfo &LI,
3771 ScopDetection &SD, ScalarEvolution &SE,
3772 OptimizationRemarkEmitter &ORE)
3773 : AA(AA), DL(DL), DT(DT), LI(LI), SD(SD), SE(SE), ORE(ORE) {
3774 DebugLoc Beg, End;
3775 auto P = getBBPairForRegion(R);
3776 getDebugLocations(P, Beg, End);
3777
3778 std::string Msg = "SCoP begins here.";
3779 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEntry", Beg, P.first)
3780 << Msg);
3781
3782 buildScop(*R, AC);
3783
3784 POLLY_DEBUG(dbgs() << *scop);
3785
3786 if (!scop->hasFeasibleRuntimeContext()) {
3787 InfeasibleScops++;
3788 Msg = "SCoP ends here but was dismissed.";
3789 POLLY_DEBUG(dbgs() << "SCoP detected but dismissed\n");
3790 RecordedAssumptions.clear();
3791 scop.reset();
3792 } else {
3793 Msg = "SCoP ends here.";
3794 ++ScopFound;
3795 if (scop->getMaxLoopDepth() > 0)
3796 ++RichScopFound;
3797 }
3798
3799 if (R->isTopLevelRegion())
3800 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.first)
3801 << Msg);
3802 else
3803 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.second)
3804 << Msg);
3805}
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")