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