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