blob: bbb6075847364a52686e826a1f258a27b3a261e4 [file] [log] [blame]
Johannes Doerfert58a7c752015-09-28 09:48:53 +00001//===--------- ScopInfo.cpp - Create Scops from LLVM IR ------------------===//
Tobias Grosser75805372011-04-29 06:27:02 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Create a polyhedral description for a static control flow region.
11//
12// The pass creates a polyhedral description of the Scops detected by the Scop
13// detection derived from their LLVM-IR code.
14//
Tobias Grossera5605d32014-10-29 19:58:28 +000015// This representation is shared among several tools in the polyhedral
Tobias Grosser75805372011-04-29 06:27:02 +000016// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
17//
18//===----------------------------------------------------------------------===//
19
Tobias Grosser5624d3c2015-12-21 12:38:56 +000020#include "polly/ScopInfo.h"
Tobias Grosser75805372011-04-29 06:27:02 +000021#include "polly/LinkAllPasses.h"
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000022#include "polly/Options.h"
Tobias Grosser75805372011-04-29 06:27:02 +000023#include "polly/Support/GICHelper.h"
Tobias Grosser60b54f12011-11-08 15:41:28 +000024#include "polly/Support/SCEVValidator.h"
Tobias Grosser83628182013-05-07 08:11:54 +000025#include "polly/Support/ScopHelper.h"
Tobias Grosser9737c7b2015-11-22 11:06:51 +000026#include "llvm/ADT/DepthFirstIterator.h"
Tobias Grosserf4c24b22015-04-05 13:11:54 +000027#include "llvm/ADT/MapVector.h"
Tobias Grosserc2bb0cb2015-09-25 09:49:19 +000028#include "llvm/ADT/PostOrderIterator.h"
29#include "llvm/ADT/STLExtras.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000030#include "llvm/ADT/SetVector.h"
Tobias Grosser83628182013-05-07 08:11:54 +000031#include "llvm/ADT/Statistic.h"
Hongbin Zheng86a37742012-04-25 08:01:38 +000032#include "llvm/ADT/StringExtras.h"
Johannes Doerfertb164c792014-09-18 11:17:17 +000033#include "llvm/Analysis/AliasAnalysis.h"
Johannes Doerfert2af10e22015-11-12 03:25:01 +000034#include "llvm/Analysis/AssumptionCache.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000035#include "llvm/Analysis/LoopInfo.h"
Tobias Grosserc2bb0cb2015-09-25 09:49:19 +000036#include "llvm/Analysis/LoopIterator.h"
Tobias Grosser83628182013-05-07 08:11:54 +000037#include "llvm/Analysis/RegionIterator.h"
38#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Johannes Doerfert48fe86f2015-11-12 02:32:32 +000039#include "llvm/IR/DiagnosticInfo.h"
Tobias Grosser75805372011-04-29 06:27:02 +000040#include "llvm/Support/Debug.h"
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000041#include "isl/aff.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000042#include "isl/constraint.h"
Tobias Grosserf5338802011-10-06 00:03:35 +000043#include "isl/local_space.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000044#include "isl/map.h"
Tobias Grosser4a8e3562011-12-07 07:42:51 +000045#include "isl/options.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000046#include "isl/printer.h"
Tobias Grosser808cd692015-07-14 09:33:13 +000047#include "isl/schedule.h"
48#include "isl/schedule_node.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000049#include "isl/set.h"
50#include "isl/union_map.h"
Tobias Grossercd524dc2015-05-09 09:36:38 +000051#include "isl/union_set.h"
Tobias Grosseredab1352013-06-21 06:41:31 +000052#include "isl/val.h"
Tobias Grosser75805372011-04-29 06:27:02 +000053#include <sstream>
54#include <string>
55#include <vector>
56
57using namespace llvm;
58using namespace polly;
59
Chandler Carruth95fef942014-04-22 03:30:19 +000060#define DEBUG_TYPE "polly-scops"
61
Tobias Grosser74394f02013-01-14 22:40:23 +000062STATISTIC(ScopFound, "Number of valid Scops");
63STATISTIC(RichScopFound, "Number of Scops containing a loop");
Tobias Grosser75805372011-04-29 06:27:02 +000064
Tobias Grosser75dc40c2015-12-20 13:31:48 +000065// The maximal number of basic sets we allow during domain construction to
66// be created. More complex scops will result in very high compile time and
67// are also unlikely to result in good code
68static int const MaxConjunctsInDomain = 20;
69
Michael Kruse7bf39442015-09-10 12:46:52 +000070static cl::opt<bool> ModelReadOnlyScalars(
71 "polly-analyze-read-only-scalars",
72 cl::desc("Model read-only scalar values in the scop description"),
73 cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::cat(PollyCategory));
74
Johannes Doerfert9e7b17b2014-08-18 00:40:13 +000075// Multiplicative reductions can be disabled separately as these kind of
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000076// operations can overflow easily. Additive reductions and bit operations
77// are in contrast pretty stable.
Tobias Grosser483a90d2014-07-09 10:50:10 +000078static cl::opt<bool> DisableMultiplicativeReductions(
79 "polly-disable-multiplicative-reductions",
80 cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore,
81 cl::init(false), cl::cat(PollyCategory));
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000082
Johannes Doerfert9143d672014-09-27 11:02:39 +000083static cl::opt<unsigned> RunTimeChecksMaxParameters(
84 "polly-rtc-max-parameters",
85 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden,
86 cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory));
87
Tobias Grosser71500722015-03-28 15:11:14 +000088static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup(
89 "polly-rtc-max-arrays-per-group",
90 cl::desc("The maximal number of arrays to compare in each alias group."),
91 cl::Hidden, cl::ZeroOrMore, cl::init(20), cl::cat(PollyCategory));
Tobias Grosser8a9c2352015-08-16 10:19:29 +000092static cl::opt<std::string> UserContextStr(
93 "polly-context", cl::value_desc("isl parameter set"),
94 cl::desc("Provide additional constraints on the context parameters"),
95 cl::init(""), cl::cat(PollyCategory));
Tobias Grosser71500722015-03-28 15:11:14 +000096
Tobias Grosserd83b8a82015-08-20 19:08:11 +000097static cl::opt<bool> DetectReductions("polly-detect-reductions",
98 cl::desc("Detect and exploit reductions"),
99 cl::Hidden, cl::ZeroOrMore,
100 cl::init(true), cl::cat(PollyCategory));
101
Tobias Grosser20a4c0c2015-11-11 16:22:36 +0000102static cl::opt<int> MaxDisjunctsAssumed(
103 "polly-max-disjuncts-assumed",
104 cl::desc("The maximal number of disjuncts we allow in the assumption "
105 "context (this bounds compile time)"),
106 cl::Hidden, cl::ZeroOrMore, cl::init(150), cl::cat(PollyCategory));
107
Tobias Grosser4927c8e2015-11-24 12:50:02 +0000108static cl::opt<bool> IgnoreIntegerWrapping(
109 "polly-ignore-integer-wrapping",
110 cl::desc("Do not build run-time checks to proof absence of integer "
111 "wrapping"),
112 cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory));
113
Michael Kruse7bf39442015-09-10 12:46:52 +0000114//===----------------------------------------------------------------------===//
Michael Kruse7bf39442015-09-10 12:46:52 +0000115
Michael Kruse046dde42015-08-10 13:01:57 +0000116// Create a sequence of two schedules. Either argument may be null and is
117// interpreted as the empty schedule. Can also return null if both schedules are
118// empty.
119static __isl_give isl_schedule *
120combineInSequence(__isl_take isl_schedule *Prev,
121 __isl_take isl_schedule *Succ) {
122 if (!Prev)
123 return Succ;
124 if (!Succ)
125 return Prev;
126
127 return isl_schedule_sequence(Prev, Succ);
128}
129
Johannes Doerferte7044942015-02-24 11:58:30 +0000130static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S,
131 const ConstantRange &Range,
132 int dim,
133 enum isl_dim_type type) {
134 isl_val *V;
135 isl_ctx *ctx = isl_set_get_ctx(S);
136
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000137 bool useLowerUpperBound = Range.isSignWrappedSet() && !Range.isFullSet();
138 const auto LB = useLowerUpperBound ? Range.getLower() : Range.getSignedMin();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000139 V = isl_valFromAPInt(ctx, LB, true);
Johannes Doerferte7044942015-02-24 11:58:30 +0000140 isl_set *SLB = isl_set_lower_bound_val(isl_set_copy(S), type, dim, V);
141
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000142 const auto UB = useLowerUpperBound ? Range.getUpper() : Range.getSignedMax();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000143 V = isl_valFromAPInt(ctx, UB, true);
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000144 if (useLowerUpperBound)
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000145 V = isl_val_sub_ui(V, 1);
Johannes Doerferte7044942015-02-24 11:58:30 +0000146 isl_set *SUB = isl_set_upper_bound_val(S, type, dim, V);
147
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000148 if (useLowerUpperBound)
Johannes Doerferte7044942015-02-24 11:58:30 +0000149 return isl_set_union(SLB, SUB);
150 else
151 return isl_set_intersect(SLB, SUB);
152}
153
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000154static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) {
155 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr);
156 if (!BasePtrLI)
157 return nullptr;
158
159 if (!S->getRegion().contains(BasePtrLI))
160 return nullptr;
161
162 ScalarEvolution &SE = *S->getSE();
163
164 auto *OriginBaseSCEV =
165 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand()));
166 if (!OriginBaseSCEV)
167 return nullptr;
168
169 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV);
170 if (!OriginBaseSCEVUnknown)
171 return nullptr;
172
Tobias Grosser6abc75a2015-11-10 17:31:31 +0000173 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(),
Tobias Grossera535dff2015-12-13 19:59:01 +0000174 ScopArrayInfo::MK_Array);
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000175}
176
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000177ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
Tobias Grossera535dff2015-12-13 19:59:01 +0000178 ArrayRef<const SCEV *> Sizes, enum MemoryKind Kind,
Johannes Doerfert55b3d8b2015-11-12 20:15:08 +0000179 const DataLayout &DL, Scop *S)
180 : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) {
Tobias Grosser92245222015-07-28 14:53:44 +0000181 std::string BasePtrName =
Tobias Grossera535dff2015-12-13 19:59:01 +0000182 getIslCompatibleName("MemRef_", BasePtr, Kind == MK_PHI ? "__phi" : "");
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000183 Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000184
Tobias Grosserd840fc72016-02-04 13:18:42 +0000185 updateSizes(Sizes, ElementType);
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000186 BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
187 if (BasePtrOriginSAI)
188 const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000189}
190
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000191__isl_give isl_space *ScopArrayInfo::getSpace() const {
192 auto Space =
193 isl_space_set_alloc(isl_id_get_ctx(Id), 0, getNumberOfDimensions());
194 Space = isl_space_set_tuple_id(Space, isl_dim_set, isl_id_copy(Id));
195 return Space;
196}
197
Tobias Grosserd840fc72016-02-04 13:18:42 +0000198bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes,
199 Type *NewElementType) {
200 auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType);
201 auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType);
202
203 if (NewElementSize != OldElementSize) {
204 if (NewElementSize % OldElementSize == 0 &&
205 NewElementSize < OldElementSize) {
206 ElementType = NewElementType;
207 } else {
208 auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize);
209 ElementType = IntegerType::get(ElementType->getContext(), GCD);
210 }
211 }
212
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000213 int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
214 int ExtraDimsNew = NewSizes.size() - SharedDims;
215 int ExtraDimsOld = DimensionSizes.size() - SharedDims;
Tobias Grosser8286b832015-11-02 11:29:32 +0000216 for (int i = 0; i < SharedDims; i++)
217 if (NewSizes[i + ExtraDimsNew] != DimensionSizes[i + ExtraDimsOld])
218 return false;
219
220 if (DimensionSizes.size() >= NewSizes.size())
221 return true;
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000222
223 DimensionSizes.clear();
224 DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(),
225 NewSizes.end());
226 for (isl_pw_aff *Size : DimensionSizesPw)
227 isl_pw_aff_free(Size);
228 DimensionSizesPw.clear();
229 for (const SCEV *Expr : DimensionSizes) {
230 isl_pw_aff *Size = S.getPwAff(Expr);
231 DimensionSizesPw.push_back(Size);
232 }
Tobias Grosser8286b832015-11-02 11:29:32 +0000233 return true;
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000234}
235
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000236ScopArrayInfo::~ScopArrayInfo() {
237 isl_id_free(Id);
238 for (isl_pw_aff *Size : DimensionSizesPw)
239 isl_pw_aff_free(Size);
240}
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000241
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000242std::string ScopArrayInfo::getName() const { return isl_id_get_name(Id); }
243
244int ScopArrayInfo::getElemSizeInBytes() const {
Johannes Doerfert55b3d8b2015-11-12 20:15:08 +0000245 return DL.getTypeAllocSize(ElementType);
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000246}
247
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000248isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); }
249
250void ScopArrayInfo::dump() const { print(errs()); }
251
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000252void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const {
Tobias Grosser4ea2e072015-11-10 14:02:54 +0000253 OS.indent(8) << *getElementType() << " " << getName();
254 if (getNumberOfDimensions() > 0)
255 OS << "[*]";
Tobias Grosser26253842015-11-10 14:24:21 +0000256 for (unsigned u = 1; u < getNumberOfDimensions(); u++) {
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000257 OS << "[";
258
Tobias Grosser26253842015-11-10 14:24:21 +0000259 if (SizeAsPwAff) {
260 auto Size = getDimensionSizePw(u);
261 OS << " " << Size << " ";
262 isl_pw_aff_free(Size);
263 } else {
264 OS << *getDimensionSize(u);
265 }
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000266
267 OS << "]";
268 }
269
Tobias Grosser4ea2e072015-11-10 14:02:54 +0000270 OS << ";";
271
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000272 if (BasePtrOriginSAI)
273 OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]";
274
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000275 OS << " // Element size " << getElemSizeInBytes() << "\n";
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000276}
277
278const ScopArrayInfo *
279ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) {
280 isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out);
281 assert(Id && "Output dimension didn't have an ID");
282 return getFromId(Id);
283}
284
285const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) {
286 void *User = isl_id_get_user(Id);
287 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
288 isl_id_free(Id);
289 return SAI;
290}
291
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000292void MemoryAccess::updateDimensionality() {
293 auto ArraySpace = getScopArrayInfo()->getSpace();
294 auto AccessSpace = isl_space_range(isl_map_get_space(AccessRelation));
295
296 auto DimsArray = isl_space_dim(ArraySpace, isl_dim_set);
297 auto DimsAccess = isl_space_dim(AccessSpace, isl_dim_set);
298 auto DimsMissing = DimsArray - DimsAccess;
299
Tobias Grosserd840fc72016-02-04 13:18:42 +0000300 auto Map = isl_map_from_domain_and_range(
301 isl_set_universe(AccessSpace),
302 isl_set_universe(isl_space_copy(ArraySpace)));
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000303
304 for (unsigned i = 0; i < DimsMissing; i++)
305 Map = isl_map_fix_si(Map, isl_dim_out, i, 0);
306
307 for (unsigned i = DimsMissing; i < DimsArray; i++)
308 Map = isl_map_equate(Map, isl_dim_in, i - DimsMissing, isl_dim_out, i);
309
310 AccessRelation = isl_map_apply_range(AccessRelation, Map);
Roman Gareev10595a12016-01-08 14:01:59 +0000311
Tobias Grosserd840fc72016-02-04 13:18:42 +0000312 // Introduce multi-element accesses in case the type loaded by this memory
313 // access is larger than the canonical element type of the array.
314 //
315 // An access ((float *)A)[i] to an array char *A is modeled as
316 // {[i] -> A[o] : 4 i <= o <= 4 i + 3
317 unsigned ArrayElemSize = getScopArrayInfo()->getElemSizeInBytes();
318 if (ElemBytes > ArrayElemSize) {
319 assert(ElemBytes % ArrayElemSize == 0 &&
320 "Loaded element size should be multiple of canonical element size");
321 auto Map = isl_map_from_domain_and_range(
322 isl_set_universe(isl_space_copy(ArraySpace)),
323 isl_set_universe(isl_space_copy(ArraySpace)));
324 for (unsigned i = 0; i < DimsArray - 1; i++)
325 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
326
327 isl_ctx *Ctx;
328 isl_constraint *C;
329 isl_local_space *LS;
330
331 LS = isl_local_space_from_space(isl_map_get_space(Map));
332 Ctx = isl_map_get_ctx(Map);
333 int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes();
334
335 C = isl_constraint_alloc_inequality(isl_local_space_copy(LS));
336 C = isl_constraint_set_constant_val(C, isl_val_int_from_si(Ctx, Num - 1));
337 C = isl_constraint_set_coefficient_si(C, isl_dim_in,
338 DimsArray - 1 - DimsMissing, Num);
339 C = isl_constraint_set_coefficient_si(C, isl_dim_out, DimsArray - 1, -1);
340 Map = isl_map_add_constraint(Map, C);
341
342 C = isl_constraint_alloc_inequality(LS);
343 C = isl_constraint_set_coefficient_si(C, isl_dim_in,
344 DimsArray - 1 - DimsMissing, -Num);
345 C = isl_constraint_set_coefficient_si(C, isl_dim_out, DimsArray - 1, 1);
346 C = isl_constraint_set_constant_val(C, isl_val_int_from_si(Ctx, 0));
347 Map = isl_map_add_constraint(Map, C);
348 AccessRelation = isl_map_apply_range(AccessRelation, Map);
349 }
350
351 isl_space_free(ArraySpace);
352
Roman Gareev10595a12016-01-08 14:01:59 +0000353 assumeNoOutOfBound();
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000354}
355
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000356const std::string
357MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
358 switch (RT) {
359 case MemoryAccess::RT_NONE:
360 llvm_unreachable("Requested a reduction operator string for a memory "
361 "access which isn't a reduction");
362 case MemoryAccess::RT_ADD:
363 return "+";
364 case MemoryAccess::RT_MUL:
365 return "*";
366 case MemoryAccess::RT_BOR:
367 return "|";
368 case MemoryAccess::RT_BXOR:
369 return "^";
370 case MemoryAccess::RT_BAND:
371 return "&";
372 }
373 llvm_unreachable("Unknown reduction type");
374 return "";
375}
376
Johannes Doerfertf6183392014-07-01 20:52:51 +0000377/// @brief Return the reduction type for a given binary operator
378static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp,
379 const Instruction *Load) {
380 if (!BinOp)
381 return MemoryAccess::RT_NONE;
382 switch (BinOp->getOpcode()) {
383 case Instruction::FAdd:
384 if (!BinOp->hasUnsafeAlgebra())
385 return MemoryAccess::RT_NONE;
386 // Fall through
387 case Instruction::Add:
388 return MemoryAccess::RT_ADD;
389 case Instruction::Or:
390 return MemoryAccess::RT_BOR;
391 case Instruction::Xor:
392 return MemoryAccess::RT_BXOR;
393 case Instruction::And:
394 return MemoryAccess::RT_BAND;
395 case Instruction::FMul:
396 if (!BinOp->hasUnsafeAlgebra())
397 return MemoryAccess::RT_NONE;
398 // Fall through
399 case Instruction::Mul:
400 if (DisableMultiplicativeReductions)
401 return MemoryAccess::RT_NONE;
402 return MemoryAccess::RT_MUL;
403 default:
404 return MemoryAccess::RT_NONE;
405 }
406}
Tobias Grosser5fd8c092015-09-17 17:28:15 +0000407
Tobias Grosser5fd8c092015-09-17 17:28:15 +0000408/// @brief Derive the individual index expressions from a GEP instruction
409///
410/// This function optimistically assumes the GEP references into a fixed size
411/// array. If this is actually true, this function returns a list of array
412/// subscript expressions as SCEV as well as a list of integers describing
413/// the size of the individual array dimensions. Both lists have either equal
414/// length of the size list is one element shorter in case there is no known
415/// size available for the outermost array dimension.
416///
417/// @param GEP The GetElementPtr instruction to analyze.
418///
419/// @return A tuple with the subscript expressions and the dimension sizes.
420static std::tuple<std::vector<const SCEV *>, std::vector<int>>
421getIndexExpressionsFromGEP(GetElementPtrInst *GEP, ScalarEvolution &SE) {
422 std::vector<const SCEV *> Subscripts;
423 std::vector<int> Sizes;
424
425 Type *Ty = GEP->getPointerOperandType();
426
427 bool DroppedFirstDim = false;
428
Michael Kruse26ed65e2015-09-24 17:32:49 +0000429 for (unsigned i = 1; i < GEP->getNumOperands(); i++) {
Tobias Grosser5fd8c092015-09-17 17:28:15 +0000430
431 const SCEV *Expr = SE.getSCEV(GEP->getOperand(i));
432
433 if (i == 1) {
434 if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
435 Ty = PtrTy->getElementType();
436 } else if (auto ArrayTy = dyn_cast<ArrayType>(Ty)) {
437 Ty = ArrayTy->getElementType();
438 } else {
439 Subscripts.clear();
440 Sizes.clear();
441 break;
442 }
443 if (auto Const = dyn_cast<SCEVConstant>(Expr))
444 if (Const->getValue()->isZero()) {
445 DroppedFirstDim = true;
446 continue;
447 }
448 Subscripts.push_back(Expr);
449 continue;
450 }
451
452 auto ArrayTy = dyn_cast<ArrayType>(Ty);
453 if (!ArrayTy) {
454 Subscripts.clear();
455 Sizes.clear();
456 break;
457 }
458
459 Subscripts.push_back(Expr);
460 if (!(DroppedFirstDim && i == 2))
461 Sizes.push_back(ArrayTy->getNumElements());
462
463 Ty = ArrayTy->getElementType();
464 }
465
466 return std::make_tuple(Subscripts, Sizes);
467}
468
Tobias Grosser75805372011-04-29 06:27:02 +0000469MemoryAccess::~MemoryAccess() {
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000470 isl_id_free(Id);
Tobias Grosser54a86e62011-08-18 06:31:46 +0000471 isl_map_free(AccessRelation);
Tobias Grosser166c4222015-09-05 07:46:40 +0000472 isl_map_free(NewAccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000473}
474
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000475const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const {
476 isl_id *ArrayId = getArrayId();
477 void *User = isl_id_get_user(ArrayId);
478 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
479 isl_id_free(ArrayId);
480 return SAI;
481}
482
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000483__isl_give isl_id *MemoryAccess::getArrayId() const {
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000484 return isl_map_get_tuple_id(AccessRelation, isl_dim_out);
485}
486
Tobias Grosserd840fc72016-02-04 13:18:42 +0000487__isl_give isl_map *MemoryAccess::getAddressFunction() const {
488 return isl_map_lexmin(getAccessRelation());
489}
490
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000491__isl_give isl_pw_multi_aff *MemoryAccess::applyScheduleToAccessRelation(
492 __isl_take isl_union_map *USchedule) const {
Johannes Doerferta99130f2014-10-13 12:58:03 +0000493 isl_map *Schedule, *ScheduledAccRel;
494 isl_union_set *UDomain;
495
496 UDomain = isl_union_set_from_set(getStatement()->getDomain());
497 USchedule = isl_union_map_intersect_domain(USchedule, UDomain);
498 Schedule = isl_map_from_union_map(USchedule);
Tobias Grosserd840fc72016-02-04 13:18:42 +0000499 ScheduledAccRel = isl_map_apply_domain(getAddressFunction(), Schedule);
Johannes Doerferta99130f2014-10-13 12:58:03 +0000500 return isl_pw_multi_aff_from_map(ScheduledAccRel);
501}
502
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000503__isl_give isl_map *MemoryAccess::getOriginalAccessRelation() const {
Tobias Grosser5d453812011-10-06 00:04:11 +0000504 return isl_map_copy(AccessRelation);
505}
506
Johannes Doerferta99130f2014-10-13 12:58:03 +0000507std::string MemoryAccess::getOriginalAccessRelationStr() const {
Tobias Grosser5d453812011-10-06 00:04:11 +0000508 return stringFromIslObj(AccessRelation);
509}
510
Johannes Doerferta99130f2014-10-13 12:58:03 +0000511__isl_give isl_space *MemoryAccess::getOriginalAccessRelationSpace() const {
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000512 return isl_map_get_space(AccessRelation);
513}
514
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000515__isl_give isl_map *MemoryAccess::getNewAccessRelation() const {
Tobias Grosser166c4222015-09-05 07:46:40 +0000516 return isl_map_copy(NewAccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000517}
518
Tobias Grosser6f730082015-09-05 07:46:47 +0000519std::string MemoryAccess::getNewAccessRelationStr() const {
520 return stringFromIslObj(NewAccessRelation);
521}
522
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000523__isl_give isl_basic_map *
524MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
Tobias Grosser084d8f72012-05-29 09:29:44 +0000525 isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1);
Tobias Grossered295662012-09-11 13:50:21 +0000526 Space = isl_space_align_params(Space, Statement->getDomainSpace());
Tobias Grosser75805372011-04-29 06:27:02 +0000527
Tobias Grosser084d8f72012-05-29 09:29:44 +0000528 return isl_basic_map_from_domain_and_range(
Tobias Grosserabfbe632013-02-05 12:09:06 +0000529 isl_basic_set_universe(Statement->getDomainSpace()),
530 isl_basic_set_universe(Space));
Tobias Grosser75805372011-04-29 06:27:02 +0000531}
532
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000533// Formalize no out-of-bound access assumption
534//
535// When delinearizing array accesses we optimistically assume that the
536// delinearized accesses do not access out of bound locations (the subscript
537// expression of each array evaluates for each statement instance that is
538// executed to a value that is larger than zero and strictly smaller than the
539// size of the corresponding dimension). The only exception is the outermost
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000540// dimension for which we do not need to assume any upper bound. At this point
541// we formalize this assumption to ensure that at code generation time the
542// relevant run-time checks can be generated.
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000543//
544// To find the set of constraints necessary to avoid out of bound accesses, we
545// first build the set of data locations that are not within array bounds. We
546// then apply the reverse access relation to obtain the set of iterations that
547// may contain invalid accesses and reduce this set of iterations to the ones
548// that are actually executed by intersecting them with the domain of the
549// statement. If we now project out all loop dimensions, we obtain a set of
550// parameters that may cause statement instances to be executed that may
551// possibly yield out of bound memory accesses. The complement of these
552// constraints is the set of constraints that needs to be assumed to ensure such
553// statement instances are never executed.
Michael Krusee2bccbb2015-09-18 19:59:43 +0000554void MemoryAccess::assumeNoOutOfBound() {
Johannes Doerferta99130f2014-10-13 12:58:03 +0000555 isl_space *Space = isl_space_range(getOriginalAccessRelationSpace());
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000556 isl_set *Outside = isl_set_empty(isl_space_copy(Space));
Roman Gareev10595a12016-01-08 14:01:59 +0000557 for (int i = 1, Size = isl_space_dim(Space, isl_dim_set); i < Size; ++i) {
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000558 isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space));
559 isl_pw_aff *Var =
560 isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i);
561 isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS);
562
563 isl_set *DimOutside;
564
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000565 DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero);
Roman Gareev10595a12016-01-08 14:01:59 +0000566 isl_pw_aff *SizeE = getScopArrayInfo()->getDimensionSizePw(i);
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000567 SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in,
568 isl_space_dim(Space, isl_dim_set));
569 SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in,
570 isl_space_get_tuple_id(Space, isl_dim_set));
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000571
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000572 DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var));
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000573
574 Outside = isl_set_union(Outside, DimOutside);
575 }
576
577 Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation()));
578 Outside = isl_set_intersect(Outside, Statement->getDomain());
579 Outside = isl_set_params(Outside);
Tobias Grosserf54bb772015-06-26 12:09:28 +0000580
581 // Remove divs to avoid the construction of overly complicated assumptions.
582 // Doing so increases the set of parameter combinations that are assumed to
583 // not appear. This is always save, but may make the resulting run-time check
584 // bail out more often than strictly necessary.
585 Outside = isl_set_remove_divs(Outside);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000586 Outside = isl_set_complement(Outside);
Michael Krusead28e5a2016-01-26 13:33:15 +0000587 Statement->getParent()->addAssumption(
588 INBOUNDS, Outside,
589 getAccessInstruction() ? getAccessInstruction()->getDebugLoc() : nullptr);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000590 isl_space_free(Space);
591}
592
Johannes Doerferte7044942015-02-24 11:58:30 +0000593void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) {
594 ScalarEvolution *SE = Statement->getParent()->getSE();
595
Michael Kruse70131d32016-01-27 17:09:17 +0000596 Value *Ptr = MemAccInst(getAccessInstruction()).getPointerOperand();
Johannes Doerferte7044942015-02-24 11:58:30 +0000597 if (!Ptr || !SE->isSCEVable(Ptr->getType()))
598 return;
599
600 auto *PtrSCEV = SE->getSCEV(Ptr);
601 if (isa<SCEVCouldNotCompute>(PtrSCEV))
602 return;
603
604 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
605 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
606 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
607
608 const ConstantRange &Range = SE->getSignedRange(PtrSCEV);
609 if (Range.isFullSet())
610 return;
611
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000612 bool isWrapping = Range.isSignWrappedSet();
Johannes Doerferte7044942015-02-24 11:58:30 +0000613 unsigned BW = Range.getBitWidth();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000614 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin();
615 const auto UB = isWrapping ? Range.getUpper() : Range.getSignedMax();
616
617 auto Min = LB.sdiv(APInt(BW, ElementSize));
618 auto Max = (UB - APInt(BW, 1)).sdiv(APInt(BW, ElementSize));
Johannes Doerferte7044942015-02-24 11:58:30 +0000619
620 isl_set *AccessRange = isl_map_range(isl_map_copy(AccessRelation));
621 AccessRange =
622 addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, isl_dim_set);
623 AccessRelation = isl_map_intersect_range(AccessRelation, AccessRange);
624}
625
Michael Krusee2bccbb2015-09-18 19:59:43 +0000626__isl_give isl_map *MemoryAccess::foldAccess(__isl_take isl_map *AccessRelation,
Tobias Grosser619190d2015-03-30 17:22:28 +0000627 ScopStmt *Statement) {
Michael Krusee2bccbb2015-09-18 19:59:43 +0000628 int Size = Subscripts.size();
Tobias Grosser619190d2015-03-30 17:22:28 +0000629
630 for (int i = Size - 2; i >= 0; --i) {
631 isl_space *Space;
632 isl_map *MapOne, *MapTwo;
Michael Krusee2bccbb2015-09-18 19:59:43 +0000633 isl_pw_aff *DimSize = Statement->getPwAff(Sizes[i]);
Tobias Grosser619190d2015-03-30 17:22:28 +0000634
635 isl_space *SpaceSize = isl_pw_aff_get_space(DimSize);
636 isl_pw_aff_free(DimSize);
637 isl_id *ParamId = isl_space_get_dim_id(SpaceSize, isl_dim_param, 0);
638
639 Space = isl_map_get_space(AccessRelation);
640 Space = isl_space_map_from_set(isl_space_range(Space));
641 Space = isl_space_align_params(Space, SpaceSize);
642
643 int ParamLocation = isl_space_find_dim_by_id(Space, isl_dim_param, ParamId);
644 isl_id_free(ParamId);
645
646 MapOne = isl_map_universe(isl_space_copy(Space));
647 for (int j = 0; j < Size; ++j)
648 MapOne = isl_map_equate(MapOne, isl_dim_in, j, isl_dim_out, j);
649 MapOne = isl_map_lower_bound_si(MapOne, isl_dim_in, i + 1, 0);
650
651 MapTwo = isl_map_universe(isl_space_copy(Space));
652 for (int j = 0; j < Size; ++j)
653 if (j < i || j > i + 1)
654 MapTwo = isl_map_equate(MapTwo, isl_dim_in, j, isl_dim_out, j);
655
656 isl_local_space *LS = isl_local_space_from_space(Space);
657 isl_constraint *C;
658 C = isl_equality_alloc(isl_local_space_copy(LS));
659 C = isl_constraint_set_constant_si(C, -1);
660 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i, 1);
661 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i, -1);
662 MapTwo = isl_map_add_constraint(MapTwo, C);
663 C = isl_equality_alloc(LS);
664 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i + 1, 1);
665 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i + 1, -1);
666 C = isl_constraint_set_coefficient_si(C, isl_dim_param, ParamLocation, 1);
667 MapTwo = isl_map_add_constraint(MapTwo, C);
668 MapTwo = isl_map_upper_bound_si(MapTwo, isl_dim_in, i + 1, -1);
669
670 MapOne = isl_map_union(MapOne, MapTwo);
671 AccessRelation = isl_map_apply_range(AccessRelation, MapOne);
672 }
673 return AccessRelation;
674}
675
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000676/// @brief Check if @p Expr is divisible by @p Size.
677static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) {
678
679 // Only one factor needs to be divisible.
680 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
681 for (auto *FactorExpr : MulExpr->operands())
682 if (isDivisible(FactorExpr, Size, SE))
683 return true;
684 return false;
685 }
686
687 // For other n-ary expressions (Add, AddRec, Max,...) all operands need
688 // to be divisble.
689 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
690 for (auto *OpExpr : NAryExpr->operands())
691 if (!isDivisible(OpExpr, Size, SE))
692 return false;
693 return true;
694 }
695
696 auto *SizeSCEV = SE.getConstant(Expr->getType(), Size);
697 auto *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
698 auto *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
699 return MulSCEV == Expr;
700}
701
Michael Krusee2bccbb2015-09-18 19:59:43 +0000702void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) {
703 assert(!AccessRelation && "AccessReltation already built");
Tobias Grosser75805372011-04-29 06:27:02 +0000704
Michael Krusee2bccbb2015-09-18 19:59:43 +0000705 isl_ctx *Ctx = isl_id_get_ctx(Id);
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000706 isl_id *BaseAddrId = SAI->getBasePtrId();
Tobias Grosser5683df42011-11-09 22:34:34 +0000707
Michael Krusee2bccbb2015-09-18 19:59:43 +0000708 if (!isAffine()) {
Tobias Grosser4f967492013-06-23 05:21:18 +0000709 // We overapproximate non-affine accesses with a possible access to the
710 // whole array. For read accesses it does not make a difference, if an
711 // access must or may happen. However, for write accesses it is important to
712 // differentiate between writes that must happen and writes that may happen.
Tobias Grosser04d6ae62013-06-23 06:04:54 +0000713 AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement));
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000714 AccessRelation =
715 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
Johannes Doerferte7044942015-02-24 11:58:30 +0000716
Michael Krusee2bccbb2015-09-18 19:59:43 +0000717 computeBoundsOnAccessRelation(getElemSizeInBytes());
Tobias Grossera1879642011-12-20 10:43:14 +0000718 return;
719 }
720
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000721 Scop &S = *getStatement()->getParent();
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000722 isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0);
Tobias Grosser79baa212014-04-10 08:38:02 +0000723 AccessRelation = isl_map_universe(Space);
Tobias Grossera1879642011-12-20 10:43:14 +0000724
Michael Krusee2bccbb2015-09-18 19:59:43 +0000725 for (int i = 0, Size = Subscripts.size(); i < Size; ++i) {
726 isl_pw_aff *Affine = Statement->getPwAff(Subscripts[i]);
Tobias Grosser75805372011-04-29 06:27:02 +0000727
Sebastian Pop422e33f2014-06-03 18:16:31 +0000728 if (Size == 1) {
729 // For the non delinearized arrays, divide the access function of the last
730 // subscript by the size of the elements in the array.
Sebastian Pop18016682014-04-08 21:20:44 +0000731 //
732 // A stride one array access in C expressed as A[i] is expressed in
733 // LLVM-IR as something like A[i * elementsize]. This hides the fact that
734 // two subsequent values of 'i' index two values that are stored next to
735 // each other in memory. By this division we make this characteristic
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000736 // obvious again. However, if the index is not divisible by the element
737 // size we will bail out.
Michael Krusee2bccbb2015-09-18 19:59:43 +0000738 isl_val *v = isl_val_int_from_si(Ctx, getElemSizeInBytes());
Sebastian Pop18016682014-04-08 21:20:44 +0000739 Affine = isl_pw_aff_scale_down_val(Affine, v);
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000740
741 if (!isDivisible(Subscripts[0], getElemSizeInBytes(), *S.getSE()))
Tobias Grosser8d4f6262015-12-12 09:52:26 +0000742 S.invalidate(ALIGNMENT, AccessInstruction->getDebugLoc());
Sebastian Pop18016682014-04-08 21:20:44 +0000743 }
744
745 isl_map *SubscriptMap = isl_map_from_pw_aff(Affine);
746
Tobias Grosser79baa212014-04-10 08:38:02 +0000747 AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap);
Sebastian Pop18016682014-04-08 21:20:44 +0000748 }
749
Tobias Grosser5d51afe2016-02-02 16:46:45 +0000750 if (Sizes.size() >= 1 && !isa<SCEVConstant>(Sizes[0]))
Michael Krusee2bccbb2015-09-18 19:59:43 +0000751 AccessRelation = foldAccess(AccessRelation, Statement);
Tobias Grosser619190d2015-03-30 17:22:28 +0000752
Tobias Grosser79baa212014-04-10 08:38:02 +0000753 Space = Statement->getDomainSpace();
Tobias Grosserabfbe632013-02-05 12:09:06 +0000754 AccessRelation = isl_map_set_tuple_id(
755 AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set));
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000756 AccessRelation =
757 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
758
Tobias Grosseraa660a92015-03-30 00:07:50 +0000759 AccessRelation = isl_map_gist_domain(AccessRelation, Statement->getDomain());
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000760 isl_space_free(Space);
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000761}
Tobias Grosser30b8a092011-08-18 07:51:37 +0000762
Michael Krusecac948e2015-10-02 13:53:07 +0000763MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
Tobias Grosserf1bfd752015-11-05 20:15:37 +0000764 AccessType Type, Value *BaseAddress,
765 unsigned ElemBytes, bool Affine,
Michael Krusee2bccbb2015-09-18 19:59:43 +0000766 ArrayRef<const SCEV *> Subscripts,
767 ArrayRef<const SCEV *> Sizes, Value *AccessValue,
Tobias Grossera535dff2015-12-13 19:59:01 +0000768 ScopArrayInfo::MemoryKind Kind, StringRef BaseName)
769 : Kind(Kind), AccType(Type), RedType(RT_NONE), Statement(Stmt),
Michael Krusecac948e2015-10-02 13:53:07 +0000770 BaseAddr(BaseAddress), BaseName(BaseName), ElemBytes(ElemBytes),
771 Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst),
772 AccessValue(AccessValue), IsAffine(Affine),
Michael Krusee2bccbb2015-09-18 19:59:43 +0000773 Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(nullptr),
Tobias Grosserf1bfd752015-11-05 20:15:37 +0000774 NewAccessRelation(nullptr) {
775
776 std::string IdName = "__polly_array_ref";
777 Id = isl_id_alloc(Stmt->getParent()->getIslCtx(), IdName.c_str(), this);
778}
Michael Krusee2bccbb2015-09-18 19:59:43 +0000779
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000780void MemoryAccess::realignParams() {
Tobias Grosser6defb5b2014-04-10 08:37:44 +0000781 isl_space *ParamSpace = Statement->getParent()->getParamSpace();
Tobias Grosser37487052011-10-06 00:03:42 +0000782 AccessRelation = isl_map_align_params(AccessRelation, ParamSpace);
Tobias Grosser75805372011-04-29 06:27:02 +0000783}
784
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000785const std::string MemoryAccess::getReductionOperatorStr() const {
786 return MemoryAccess::getReductionOperatorStr(getReductionType());
787}
788
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000789__isl_give isl_id *MemoryAccess::getId() const { return isl_id_copy(Id); }
790
Johannes Doerfertf6183392014-07-01 20:52:51 +0000791raw_ostream &polly::operator<<(raw_ostream &OS,
792 MemoryAccess::ReductionType RT) {
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000793 if (RT == MemoryAccess::RT_NONE)
Johannes Doerfertf6183392014-07-01 20:52:51 +0000794 OS << "NONE";
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000795 else
796 OS << MemoryAccess::getReductionOperatorStr(RT);
Johannes Doerfertf6183392014-07-01 20:52:51 +0000797 return OS;
798}
799
Tobias Grosser75805372011-04-29 06:27:02 +0000800void MemoryAccess::print(raw_ostream &OS) const {
Johannes Doerfert4c7ce472014-10-08 10:11:33 +0000801 switch (AccType) {
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000802 case READ:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000803 OS.indent(12) << "ReadAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000804 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000805 case MUST_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000806 OS.indent(12) << "MustWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000807 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000808 case MAY_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000809 OS.indent(12) << "MayWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000810 break;
811 }
Johannes Doerfert0ff23ec2015-02-06 20:13:15 +0000812 OS << "[Reduction Type: " << getReductionType() << "] ";
Tobias Grossera535dff2015-12-13 19:59:01 +0000813 OS << "[Scalar: " << isScalarKind() << "]\n";
Michael Kruseb8d26442015-12-13 19:35:26 +0000814 OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
Tobias Grosser6f730082015-09-05 07:46:47 +0000815 if (hasNewAccessRelation())
816 OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +0000817}
818
Tobias Grosser74394f02013-01-14 22:40:23 +0000819void MemoryAccess::dump() const { print(errs()); }
Tobias Grosser75805372011-04-29 06:27:02 +0000820
821// Create a map in the size of the provided set domain, that maps from the
822// one element of the provided set domain to another element of the provided
823// set domain.
824// The mapping is limited to all points that are equal in all but the last
825// dimension and for which the last dimension of the input is strict smaller
826// than the last dimension of the output.
827//
828// getEqualAndLarger(set[i0, i1, ..., iX]):
829//
830// set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
831// : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
832//
Tobias Grosserf5338802011-10-06 00:03:35 +0000833static isl_map *getEqualAndLarger(isl_space *setDomain) {
Tobias Grosserc327932c2012-02-01 14:23:36 +0000834 isl_space *Space = isl_space_map_from_set(setDomain);
Tobias Grosser1b6ea572015-05-21 19:02:44 +0000835 isl_map *Map = isl_map_universe(Space);
Sebastian Pop40408762013-10-04 17:14:53 +0000836 unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1;
Tobias Grosser75805372011-04-29 06:27:02 +0000837
838 // Set all but the last dimension to be equal for the input and output
839 //
840 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
841 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
Sebastian Pop40408762013-10-04 17:14:53 +0000842 for (unsigned i = 0; i < lastDimension; ++i)
Tobias Grosserc327932c2012-02-01 14:23:36 +0000843 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
Tobias Grosser75805372011-04-29 06:27:02 +0000844
845 // Set the last dimension of the input to be strict smaller than the
846 // last dimension of the output.
847 //
848 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
Tobias Grosser1b6ea572015-05-21 19:02:44 +0000849 Map = isl_map_order_lt(Map, isl_dim_in, lastDimension, isl_dim_out,
850 lastDimension);
Tobias Grosserc327932c2012-02-01 14:23:36 +0000851 return Map;
Tobias Grosser75805372011-04-29 06:27:02 +0000852}
853
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000854__isl_give isl_set *
855MemoryAccess::getStride(__isl_take const isl_map *Schedule) const {
Tobias Grosserabfbe632013-02-05 12:09:06 +0000856 isl_map *S = const_cast<isl_map *>(Schedule);
Johannes Doerferta99130f2014-10-13 12:58:03 +0000857 isl_map *AccessRelation = getAccessRelation();
Sebastian Popa00a0292012-12-18 07:46:06 +0000858 isl_space *Space = isl_space_range(isl_map_get_space(S));
859 isl_map *NextScatt = getEqualAndLarger(Space);
Tobias Grosser75805372011-04-29 06:27:02 +0000860
Sebastian Popa00a0292012-12-18 07:46:06 +0000861 S = isl_map_reverse(S);
862 NextScatt = isl_map_lexmin(NextScatt);
Tobias Grosser75805372011-04-29 06:27:02 +0000863
Sebastian Popa00a0292012-12-18 07:46:06 +0000864 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S));
865 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation));
866 NextScatt = isl_map_apply_domain(NextScatt, S);
867 NextScatt = isl_map_apply_domain(NextScatt, AccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000868
Sebastian Popa00a0292012-12-18 07:46:06 +0000869 isl_set *Deltas = isl_map_deltas(NextScatt);
870 return Deltas;
Tobias Grosser75805372011-04-29 06:27:02 +0000871}
872
Sebastian Popa00a0292012-12-18 07:46:06 +0000873bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule,
Tobias Grosser28dd4862012-01-24 16:42:16 +0000874 int StrideWidth) const {
875 isl_set *Stride, *StrideX;
876 bool IsStrideX;
Tobias Grosser75805372011-04-29 06:27:02 +0000877
Sebastian Popa00a0292012-12-18 07:46:06 +0000878 Stride = getStride(Schedule);
Tobias Grosser28dd4862012-01-24 16:42:16 +0000879 StrideX = isl_set_universe(isl_set_get_space(Stride));
Tobias Grosser01c8f5f2015-08-24 22:20:46 +0000880 for (unsigned i = 0; i < isl_set_dim(StrideX, isl_dim_set) - 1; i++)
881 StrideX = isl_set_fix_si(StrideX, isl_dim_set, i, 0);
882 StrideX = isl_set_fix_si(StrideX, isl_dim_set,
883 isl_set_dim(StrideX, isl_dim_set) - 1, StrideWidth);
Roman Gareevf2bd72e2015-08-18 16:12:05 +0000884 IsStrideX = isl_set_is_subset(Stride, StrideX);
Tobias Grosser75805372011-04-29 06:27:02 +0000885
Tobias Grosser28dd4862012-01-24 16:42:16 +0000886 isl_set_free(StrideX);
Tobias Grosserdea98232012-01-17 20:34:27 +0000887 isl_set_free(Stride);
Tobias Grosserb76f38532011-08-20 11:11:25 +0000888
Tobias Grosser28dd4862012-01-24 16:42:16 +0000889 return IsStrideX;
890}
891
Sebastian Popa00a0292012-12-18 07:46:06 +0000892bool MemoryAccess::isStrideZero(const isl_map *Schedule) const {
893 return isStrideX(Schedule, 0);
Tobias Grosser75805372011-04-29 06:27:02 +0000894}
895
Sebastian Popa00a0292012-12-18 07:46:06 +0000896bool MemoryAccess::isStrideOne(const isl_map *Schedule) const {
897 return isStrideX(Schedule, 1);
Tobias Grosser75805372011-04-29 06:27:02 +0000898}
899
Tobias Grosser166c4222015-09-05 07:46:40 +0000900void MemoryAccess::setNewAccessRelation(isl_map *NewAccess) {
901 isl_map_free(NewAccessRelation);
902 NewAccessRelation = NewAccess;
Raghesh Aloor3cb66282011-07-12 17:14:03 +0000903}
Tobias Grosser75805372011-04-29 06:27:02 +0000904
905//===----------------------------------------------------------------------===//
Tobias Grossercf3942d2011-10-06 00:04:05 +0000906
Tobias Grosser808cd692015-07-14 09:33:13 +0000907isl_map *ScopStmt::getSchedule() const {
908 isl_set *Domain = getDomain();
909 if (isl_set_is_empty(Domain)) {
910 isl_set_free(Domain);
911 return isl_map_from_aff(
912 isl_aff_zero_on_domain(isl_local_space_from_space(getDomainSpace())));
913 }
914 auto *Schedule = getParent()->getSchedule();
915 Schedule = isl_union_map_intersect_domain(
916 Schedule, isl_union_set_from_set(isl_set_copy(Domain)));
917 if (isl_union_map_is_empty(Schedule)) {
918 isl_set_free(Domain);
919 isl_union_map_free(Schedule);
920 return isl_map_from_aff(
921 isl_aff_zero_on_domain(isl_local_space_from_space(getDomainSpace())));
922 }
923 auto *M = isl_map_from_union_map(Schedule);
924 M = isl_map_coalesce(M);
925 M = isl_map_gist_domain(M, Domain);
926 M = isl_map_coalesce(M);
927 return M;
928}
Tobias Grossercf3942d2011-10-06 00:04:05 +0000929
Johannes Doerfert574182d2015-08-12 10:19:50 +0000930__isl_give isl_pw_aff *ScopStmt::getPwAff(const SCEV *E) {
Johannes Doerfertcef616f2015-09-15 22:49:04 +0000931 return getParent()->getPwAff(E, isBlockStmt() ? getBasicBlock()
932 : getRegion()->getEntry());
Johannes Doerfert574182d2015-08-12 10:19:50 +0000933}
934
Tobias Grosser37eb4222014-02-20 21:43:54 +0000935void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
936 assert(isl_set_is_subset(NewDomain, Domain) &&
937 "New domain is not a subset of old domain!");
938 isl_set_free(Domain);
939 Domain = NewDomain;
Tobias Grosser75805372011-04-29 06:27:02 +0000940}
941
Michael Krusecac948e2015-10-02 13:53:07 +0000942void ScopStmt::buildAccessRelations() {
943 for (MemoryAccess *Access : MemAccs) {
944 Type *ElementType = Access->getAccessValue()->getType();
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000945
Tobias Grossera535dff2015-12-13 19:59:01 +0000946 ScopArrayInfo::MemoryKind Ty;
947 if (Access->isPHIKind())
948 Ty = ScopArrayInfo::MK_PHI;
949 else if (Access->isExitPHIKind())
950 Ty = ScopArrayInfo::MK_ExitPHI;
951 else if (Access->isValueKind())
952 Ty = ScopArrayInfo::MK_Value;
Tobias Grosser6abc75a2015-11-10 17:31:31 +0000953 else
Tobias Grossera535dff2015-12-13 19:59:01 +0000954 Ty = ScopArrayInfo::MK_Array;
Tobias Grosser6abc75a2015-11-10 17:31:31 +0000955
Johannes Doerfert80ef1102014-11-07 08:31:31 +0000956 const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
Tobias Grosser6abc75a2015-11-10 17:31:31 +0000957 Access->getBaseAddr(), ElementType, Access->Sizes, Ty);
Johannes Doerfert80ef1102014-11-07 08:31:31 +0000958
Michael Krusecac948e2015-10-02 13:53:07 +0000959 Access->buildAccessRelation(SAI);
Tobias Grosser75805372011-04-29 06:27:02 +0000960 }
961}
962
Michael Krusecac948e2015-10-02 13:53:07 +0000963void ScopStmt::addAccess(MemoryAccess *Access) {
964 Instruction *AccessInst = Access->getAccessInstruction();
965
Michael Kruse58fa3bb2015-12-22 23:25:11 +0000966 if (Access->isArrayKind()) {
967 MemoryAccessList &MAL = InstructionToAccess[AccessInst];
968 MAL.emplace_front(Access);
Michael Kruse436db622016-01-26 13:33:10 +0000969 } else if (Access->isValueKind() && Access->isWrite()) {
970 Instruction *AccessVal = cast<Instruction>(Access->getAccessValue());
971 assert(Parent.getStmtForBasicBlock(AccessVal->getParent()) == this);
972 assert(!ValueWrites.lookup(AccessVal));
973
974 ValueWrites[AccessVal] = Access;
Michael Krusead28e5a2016-01-26 13:33:15 +0000975 } else if (Access->isValueKind() && Access->isRead()) {
976 Value *AccessVal = Access->getAccessValue();
977 assert(!ValueReads.lookup(AccessVal));
978
979 ValueReads[AccessVal] = Access;
Michael Kruseee6a4fc2016-01-26 13:33:27 +0000980 } else if (Access->isAnyPHIKind() && Access->isWrite()) {
981 PHINode *PHI = cast<PHINode>(Access->getBaseAddr());
982 assert(!PHIWrites.lookup(PHI));
983
984 PHIWrites[PHI] = Access;
Michael Kruse58fa3bb2015-12-22 23:25:11 +0000985 }
986
987 MemAccs.push_back(Access);
Michael Krusecac948e2015-10-02 13:53:07 +0000988}
989
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000990void ScopStmt::realignParams() {
Johannes Doerfertf6752892014-06-13 18:01:45 +0000991 for (MemoryAccess *MA : *this)
992 MA->realignParams();
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000993
994 Domain = isl_set_align_params(Domain, Parent.getParamSpace());
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000995}
996
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +0000997/// @brief Add @p BSet to the set @p User if @p BSet is bounded.
998static isl_stat collectBoundedParts(__isl_take isl_basic_set *BSet,
999 void *User) {
1000 isl_set **BoundedParts = static_cast<isl_set **>(User);
1001 if (isl_basic_set_is_bounded(BSet))
1002 *BoundedParts = isl_set_union(*BoundedParts, isl_set_from_basic_set(BSet));
1003 else
1004 isl_basic_set_free(BSet);
1005 return isl_stat_ok;
1006}
1007
1008/// @brief Return the bounded parts of @p S.
1009static __isl_give isl_set *collectBoundedParts(__isl_take isl_set *S) {
1010 isl_set *BoundedParts = isl_set_empty(isl_set_get_space(S));
1011 isl_set_foreach_basic_set(S, collectBoundedParts, &BoundedParts);
1012 isl_set_free(S);
1013 return BoundedParts;
1014}
1015
1016/// @brief Compute the (un)bounded parts of @p S wrt. to dimension @p Dim.
1017///
1018/// @returns A separation of @p S into first an unbounded then a bounded subset,
1019/// both with regards to the dimension @p Dim.
1020static std::pair<__isl_give isl_set *, __isl_give isl_set *>
1021partitionSetParts(__isl_take isl_set *S, unsigned Dim) {
1022
1023 for (unsigned u = 0, e = isl_set_n_dim(S); u < e; u++)
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00001024 S = isl_set_lower_bound_si(S, isl_dim_set, u, 0);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001025
1026 unsigned NumDimsS = isl_set_n_dim(S);
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00001027 isl_set *OnlyDimS = isl_set_copy(S);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001028
1029 // Remove dimensions that are greater than Dim as they are not interesting.
1030 assert(NumDimsS >= Dim + 1);
1031 OnlyDimS =
1032 isl_set_project_out(OnlyDimS, isl_dim_set, Dim + 1, NumDimsS - Dim - 1);
1033
1034 // Create artificial parametric upper bounds for dimensions smaller than Dim
1035 // as we are not interested in them.
1036 OnlyDimS = isl_set_insert_dims(OnlyDimS, isl_dim_param, 0, Dim);
1037 for (unsigned u = 0; u < Dim; u++) {
1038 isl_constraint *C = isl_inequality_alloc(
1039 isl_local_space_from_space(isl_set_get_space(OnlyDimS)));
1040 C = isl_constraint_set_coefficient_si(C, isl_dim_param, u, 1);
1041 C = isl_constraint_set_coefficient_si(C, isl_dim_set, u, -1);
1042 OnlyDimS = isl_set_add_constraint(OnlyDimS, C);
1043 }
1044
1045 // Collect all bounded parts of OnlyDimS.
1046 isl_set *BoundedParts = collectBoundedParts(OnlyDimS);
1047
1048 // Create the dimensions greater than Dim again.
1049 BoundedParts = isl_set_insert_dims(BoundedParts, isl_dim_set, Dim + 1,
1050 NumDimsS - Dim - 1);
1051
1052 // Remove the artificial upper bound parameters again.
1053 BoundedParts = isl_set_remove_dims(BoundedParts, isl_dim_param, 0, Dim);
1054
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00001055 isl_set *UnboundedParts = isl_set_subtract(S, isl_set_copy(BoundedParts));
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001056 return std::make_pair(UnboundedParts, BoundedParts);
1057}
1058
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001059/// @brief Set the dimension Ids from @p From in @p To.
1060static __isl_give isl_set *setDimensionIds(__isl_keep isl_set *From,
1061 __isl_take isl_set *To) {
1062 for (unsigned u = 0, e = isl_set_n_dim(From); u < e; u++) {
1063 isl_id *DimId = isl_set_get_dim_id(From, isl_dim_set, u);
1064 To = isl_set_set_dim_id(To, isl_dim_set, u, DimId);
1065 }
1066 return To;
1067}
1068
1069/// @brief Create the conditions under which @p L @p Pred @p R is true.
Johannes Doerfert96425c22015-08-30 21:13:53 +00001070static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred,
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001071 __isl_take isl_pw_aff *L,
1072 __isl_take isl_pw_aff *R) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00001073 switch (Pred) {
1074 case ICmpInst::ICMP_EQ:
1075 return isl_pw_aff_eq_set(L, R);
1076 case ICmpInst::ICMP_NE:
1077 return isl_pw_aff_ne_set(L, R);
1078 case ICmpInst::ICMP_SLT:
1079 return isl_pw_aff_lt_set(L, R);
1080 case ICmpInst::ICMP_SLE:
1081 return isl_pw_aff_le_set(L, R);
1082 case ICmpInst::ICMP_SGT:
1083 return isl_pw_aff_gt_set(L, R);
1084 case ICmpInst::ICMP_SGE:
1085 return isl_pw_aff_ge_set(L, R);
1086 case ICmpInst::ICMP_ULT:
1087 return isl_pw_aff_lt_set(L, R);
1088 case ICmpInst::ICMP_UGT:
1089 return isl_pw_aff_gt_set(L, R);
1090 case ICmpInst::ICMP_ULE:
1091 return isl_pw_aff_le_set(L, R);
1092 case ICmpInst::ICMP_UGE:
1093 return isl_pw_aff_ge_set(L, R);
1094 default:
1095 llvm_unreachable("Non integer predicate not supported");
1096 }
1097}
1098
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001099/// @brief Create the conditions under which @p L @p Pred @p R is true.
1100///
1101/// Helper function that will make sure the dimensions of the result have the
1102/// same isl_id's as the @p Domain.
1103static __isl_give isl_set *buildConditionSet(ICmpInst::Predicate Pred,
1104 __isl_take isl_pw_aff *L,
1105 __isl_take isl_pw_aff *R,
1106 __isl_keep isl_set *Domain) {
1107 isl_set *ConsequenceCondSet = buildConditionSet(Pred, L, R);
1108 return setDimensionIds(Domain, ConsequenceCondSet);
1109}
1110
1111/// @brief Build the conditions sets for the switch @p SI in the @p Domain.
Johannes Doerfert96425c22015-08-30 21:13:53 +00001112///
1113/// This will fill @p ConditionSets with the conditions under which control
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001114/// will be moved from @p SI to its successors. Hence, @p ConditionSets will
1115/// have as many elements as @p SI has successors.
Johannes Doerfert96425c22015-08-30 21:13:53 +00001116static void
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001117buildConditionSets(Scop &S, SwitchInst *SI, Loop *L, __isl_keep isl_set *Domain,
Johannes Doerfert96425c22015-08-30 21:13:53 +00001118 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1119
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001120 Value *Condition = getConditionFromTerminator(SI);
1121 assert(Condition && "No condition for switch");
1122
1123 ScalarEvolution &SE = *S.getSE();
1124 BasicBlock *BB = SI->getParent();
1125 isl_pw_aff *LHS, *RHS;
1126 LHS = S.getPwAff(SE.getSCEVAtScope(Condition, L), BB);
1127
1128 unsigned NumSuccessors = SI->getNumSuccessors();
1129 ConditionSets.resize(NumSuccessors);
1130 for (auto &Case : SI->cases()) {
1131 unsigned Idx = Case.getSuccessorIndex();
1132 ConstantInt *CaseValue = Case.getCaseValue();
1133
1134 RHS = S.getPwAff(SE.getSCEV(CaseValue), BB);
1135 isl_set *CaseConditionSet =
1136 buildConditionSet(ICmpInst::ICMP_EQ, isl_pw_aff_copy(LHS), RHS, Domain);
1137 ConditionSets[Idx] = isl_set_coalesce(
1138 isl_set_intersect(CaseConditionSet, isl_set_copy(Domain)));
1139 }
1140
1141 assert(ConditionSets[0] == nullptr && "Default condition set was set");
1142 isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]);
1143 for (unsigned u = 2; u < NumSuccessors; u++)
1144 ConditionSetUnion =
1145 isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u]));
1146 ConditionSets[0] = setDimensionIds(
1147 Domain, isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion));
1148
1149 S.markAsOptimized();
1150 isl_pw_aff_free(LHS);
1151}
1152
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001153/// @brief Build the conditions sets for the branch condition @p Condition in
1154/// the @p Domain.
1155///
1156/// This will fill @p ConditionSets with the conditions under which control
1157/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001158/// have as many elements as @p TI has successors. If @p TI is nullptr the
1159/// context under which @p Condition is true/false will be returned as the
1160/// new elements of @p ConditionSets.
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001161static void
1162buildConditionSets(Scop &S, Value *Condition, TerminatorInst *TI, Loop *L,
1163 __isl_keep isl_set *Domain,
1164 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1165
1166 isl_set *ConsequenceCondSet = nullptr;
1167 if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
1168 if (CCond->isZero())
1169 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
1170 else
1171 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
1172 } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
1173 auto Opcode = BinOp->getOpcode();
1174 assert(Opcode == Instruction::And || Opcode == Instruction::Or);
1175
1176 buildConditionSets(S, BinOp->getOperand(0), TI, L, Domain, ConditionSets);
1177 buildConditionSets(S, BinOp->getOperand(1), TI, L, Domain, ConditionSets);
1178
1179 isl_set_free(ConditionSets.pop_back_val());
1180 isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
1181 isl_set_free(ConditionSets.pop_back_val());
1182 isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
1183
1184 if (Opcode == Instruction::And)
1185 ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1);
1186 else
1187 ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1);
1188 } else {
1189 auto *ICond = dyn_cast<ICmpInst>(Condition);
1190 assert(ICond &&
1191 "Condition of exiting branch was neither constant nor ICmp!");
1192
1193 ScalarEvolution &SE = *S.getSE();
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001194 BasicBlock *BB = TI ? TI->getParent() : nullptr;
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001195 isl_pw_aff *LHS, *RHS;
1196 LHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(0), L), BB);
1197 RHS = S.getPwAff(SE.getSCEVAtScope(ICond->getOperand(1), L), BB);
1198 ConsequenceCondSet =
1199 buildConditionSet(ICond->getPredicate(), LHS, RHS, Domain);
1200 }
1201
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001202 // If no terminator was given we are only looking for parameter constraints
1203 // under which @p Condition is true/false.
1204 if (!TI)
1205 ConsequenceCondSet = isl_set_params(ConsequenceCondSet);
1206
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001207 assert(ConsequenceCondSet);
1208 isl_set *AlternativeCondSet =
1209 isl_set_complement(isl_set_copy(ConsequenceCondSet));
1210
1211 ConditionSets.push_back(isl_set_coalesce(
1212 isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain))));
1213 ConditionSets.push_back(isl_set_coalesce(
1214 isl_set_intersect(AlternativeCondSet, isl_set_copy(Domain))));
1215}
1216
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001217/// @brief Build the conditions sets for the terminator @p TI in the @p Domain.
1218///
1219/// This will fill @p ConditionSets with the conditions under which control
1220/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
1221/// have as many elements as @p TI has successors.
1222static void
1223buildConditionSets(Scop &S, TerminatorInst *TI, Loop *L,
1224 __isl_keep isl_set *Domain,
1225 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
1226
1227 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
1228 return buildConditionSets(S, SI, L, Domain, ConditionSets);
1229
1230 assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
1231
1232 if (TI->getNumSuccessors() == 1) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00001233 ConditionSets.push_back(isl_set_copy(Domain));
1234 return;
1235 }
1236
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001237 Value *Condition = getConditionFromTerminator(TI);
1238 assert(Condition && "No condition for Terminator");
Johannes Doerfert96425c22015-08-30 21:13:53 +00001239
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001240 return buildConditionSets(S, Condition, TI, L, Domain, ConditionSets);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001241}
1242
Johannes Doerfert32ae76e2015-09-10 13:12:02 +00001243void ScopStmt::buildDomain() {
Tobias Grosser084d8f72012-05-29 09:29:44 +00001244 isl_id *Id;
Tobias Grossere19661e2011-10-07 08:46:57 +00001245
Tobias Grosser084d8f72012-05-29 09:29:44 +00001246 Id = isl_id_alloc(getIslCtx(), getBaseName(), this);
1247
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001248 Domain = getParent()->getDomainConditions(this);
Tobias Grosser084d8f72012-05-29 09:29:44 +00001249 Domain = isl_set_set_tuple_id(Domain, Id);
Tobias Grosser75805372011-04-29 06:27:02 +00001250}
1251
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001252void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP) {
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001253 isl_ctx *Ctx = Parent.getIslCtx();
1254 isl_local_space *LSpace = isl_local_space_from_space(getDomainSpace());
1255 Type *Ty = GEP->getPointerOperandType();
1256 ScalarEvolution &SE = *Parent.getSE();
Johannes Doerfert09e36972015-10-07 20:17:36 +00001257 ScopDetection &SD = Parent.getSD();
1258
1259 // The set of loads that are required to be invariant.
1260 auto &ScopRIL = *SD.getRequiredInvariantLoads(&Parent.getRegion());
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001261
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001262 std::vector<const SCEV *> Subscripts;
1263 std::vector<int> Sizes;
1264
Tobias Grosser5fd8c092015-09-17 17:28:15 +00001265 std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, SE);
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001266
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001267 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001268 Ty = PtrTy->getElementType();
1269 }
1270
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001271 int IndexOffset = Subscripts.size() - Sizes.size();
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001272
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001273 assert(IndexOffset <= 1 && "Unexpected large index offset");
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001274
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001275 for (size_t i = 0; i < Sizes.size(); i++) {
1276 auto Expr = Subscripts[i + IndexOffset];
1277 auto Size = Sizes[i];
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001278
Johannes Doerfert09e36972015-10-07 20:17:36 +00001279 InvariantLoadsSetTy AccessILS;
1280 if (!isAffineExpr(&Parent.getRegion(), Expr, SE, nullptr, &AccessILS))
1281 continue;
1282
1283 bool NonAffine = false;
1284 for (LoadInst *LInst : AccessILS)
1285 if (!ScopRIL.count(LInst))
1286 NonAffine = true;
1287
1288 if (NonAffine)
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001289 continue;
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001290
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001291 isl_pw_aff *AccessOffset = getPwAff(Expr);
1292 AccessOffset =
1293 isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001294
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001295 isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain(
1296 isl_local_space_copy(LSpace), isl_val_int_from_si(Ctx, Size)));
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001297
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001298 isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize);
1299 OutOfBound = isl_set_intersect(getDomain(), OutOfBound);
1300 OutOfBound = isl_set_params(OutOfBound);
1301 isl_set *InBound = isl_set_complement(OutOfBound);
1302 isl_set *Executed = isl_set_params(getDomain());
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001303
Tobias Grosserfaf8f6f2015-09-17 15:47:52 +00001304 // A => B == !A or B
1305 isl_set *InBoundIfExecuted =
1306 isl_set_union(isl_set_complement(Executed), InBound);
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001307
Roman Gareev10595a12016-01-08 14:01:59 +00001308 InBoundIfExecuted = isl_set_coalesce(InBoundIfExecuted);
Johannes Doerfertd84493e2015-11-12 02:33:38 +00001309 Parent.addAssumption(INBOUNDS, InBoundIfExecuted, GEP->getDebugLoc());
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001310 }
1311
1312 isl_local_space_free(LSpace);
1313}
1314
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001315void ScopStmt::deriveAssumptions(BasicBlock *Block) {
1316 for (Instruction &Inst : *Block)
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001317 if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst))
1318 deriveAssumptionsFromGEP(GEP);
1319}
1320
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00001321void ScopStmt::collectSurroundingLoops() {
1322 for (unsigned u = 0, e = isl_set_n_dim(Domain); u < e; u++) {
1323 isl_id *DimId = isl_set_get_dim_id(Domain, isl_dim_set, u);
1324 NestLoops.push_back(static_cast<Loop *>(isl_id_get_user(DimId)));
1325 isl_id_free(DimId);
1326 }
1327}
1328
Michael Kruse9d080092015-09-11 21:41:48 +00001329ScopStmt::ScopStmt(Scop &parent, Region &R)
Michael Krusecac948e2015-10-02 13:53:07 +00001330 : Parent(parent), Domain(nullptr), BB(nullptr), R(&R), Build(nullptr) {
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001331
Tobias Grosser16c44032015-07-09 07:31:45 +00001332 BaseName = getIslCompatibleName("Stmt_", R.getNameStr(), "");
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001333}
1334
Michael Kruse9d080092015-09-11 21:41:48 +00001335ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb)
Michael Krusecac948e2015-10-02 13:53:07 +00001336 : Parent(parent), Domain(nullptr), BB(&bb), R(nullptr), Build(nullptr) {
Tobias Grosser75805372011-04-29 06:27:02 +00001337
Johannes Doerfert79fc23f2014-07-24 23:48:02 +00001338 BaseName = getIslCompatibleName("Stmt_", &bb, "");
Michael Krusecac948e2015-10-02 13:53:07 +00001339}
1340
1341void ScopStmt::init() {
1342 assert(!Domain && "init must be called only once");
Tobias Grosser75805372011-04-29 06:27:02 +00001343
Johannes Doerfert32ae76e2015-09-10 13:12:02 +00001344 buildDomain();
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00001345 collectSurroundingLoops();
Michael Krusecac948e2015-10-02 13:53:07 +00001346 buildAccessRelations();
1347
1348 if (BB) {
1349 deriveAssumptions(BB);
1350 } else {
1351 for (BasicBlock *Block : R->blocks()) {
1352 deriveAssumptions(Block);
1353 }
1354 }
1355
Tobias Grosserd83b8a82015-08-20 19:08:11 +00001356 if (DetectReductions)
1357 checkForReductions();
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001358}
1359
Johannes Doerferte58a0122014-06-27 20:31:28 +00001360/// @brief Collect loads which might form a reduction chain with @p StoreMA
1361///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001362/// Check if the stored value for @p StoreMA is a binary operator with one or
1363/// two loads as operands. If the binary operand is commutative & associative,
Johannes Doerferte58a0122014-06-27 20:31:28 +00001364/// used only once (by @p StoreMA) and its load operands are also used only
1365/// once, we have found a possible reduction chain. It starts at an operand
1366/// load and includes the binary operator and @p StoreMA.
1367///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001368/// Note: We allow only one use to ensure the load and binary operator cannot
Johannes Doerferte58a0122014-06-27 20:31:28 +00001369/// escape this block or into any other store except @p StoreMA.
1370void ScopStmt::collectCandiateReductionLoads(
1371 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) {
1372 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction());
1373 if (!Store)
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001374 return;
1375
1376 // Skip if there is not one binary operator between the load and the store
1377 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand());
Johannes Doerferte58a0122014-06-27 20:31:28 +00001378 if (!BinOp)
1379 return;
1380
1381 // Skip if the binary operators has multiple uses
1382 if (BinOp->getNumUses() != 1)
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001383 return;
1384
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001385 // Skip if the opcode of the binary operator is not commutative/associative
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001386 if (!BinOp->isCommutative() || !BinOp->isAssociative())
1387 return;
1388
Johannes Doerfert9890a052014-07-01 00:32:29 +00001389 // Skip if the binary operator is outside the current SCoP
1390 if (BinOp->getParent() != Store->getParent())
1391 return;
1392
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001393 // Skip if it is a multiplicative reduction and we disabled them
1394 if (DisableMultiplicativeReductions &&
1395 (BinOp->getOpcode() == Instruction::Mul ||
1396 BinOp->getOpcode() == Instruction::FMul))
1397 return;
1398
Johannes Doerferte58a0122014-06-27 20:31:28 +00001399 // Check the binary operator operands for a candidate load
1400 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0));
1401 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1));
1402 if (!PossibleLoad0 && !PossibleLoad1)
1403 return;
1404
1405 // A load is only a candidate if it cannot escape (thus has only this use)
1406 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1)
Johannes Doerfert9890a052014-07-01 00:32:29 +00001407 if (PossibleLoad0->getParent() == Store->getParent())
Tobias Grosser35ec5fb2015-12-15 23:50:04 +00001408 Loads.push_back(&getArrayAccessFor(PossibleLoad0));
Johannes Doerferte58a0122014-06-27 20:31:28 +00001409 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1)
Johannes Doerfert9890a052014-07-01 00:32:29 +00001410 if (PossibleLoad1->getParent() == Store->getParent())
Tobias Grosser35ec5fb2015-12-15 23:50:04 +00001411 Loads.push_back(&getArrayAccessFor(PossibleLoad1));
Johannes Doerferte58a0122014-06-27 20:31:28 +00001412}
1413
1414/// @brief Check for reductions in this ScopStmt
1415///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001416/// Iterate over all store memory accesses and check for valid binary reduction
1417/// like chains. For all candidates we check if they have the same base address
1418/// and there are no other accesses which overlap with them. The base address
1419/// check rules out impossible reductions candidates early. The overlap check,
1420/// together with the "only one user" check in collectCandiateReductionLoads,
Johannes Doerferte58a0122014-06-27 20:31:28 +00001421/// guarantees that none of the intermediate results will escape during
1422/// execution of the loop nest. We basically check here that no other memory
1423/// access can access the same memory as the potential reduction.
1424void ScopStmt::checkForReductions() {
1425 SmallVector<MemoryAccess *, 2> Loads;
1426 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
1427
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001428 // First collect candidate load-store reduction chains by iterating over all
Johannes Doerferte58a0122014-06-27 20:31:28 +00001429 // stores and collecting possible reduction loads.
1430 for (MemoryAccess *StoreMA : MemAccs) {
1431 if (StoreMA->isRead())
1432 continue;
1433
1434 Loads.clear();
1435 collectCandiateReductionLoads(StoreMA, Loads);
1436 for (MemoryAccess *LoadMA : Loads)
1437 Candidates.push_back(std::make_pair(LoadMA, StoreMA));
1438 }
1439
1440 // Then check each possible candidate pair.
1441 for (const auto &CandidatePair : Candidates) {
1442 bool Valid = true;
1443 isl_map *LoadAccs = CandidatePair.first->getAccessRelation();
1444 isl_map *StoreAccs = CandidatePair.second->getAccessRelation();
1445
1446 // Skip those with obviously unequal base addresses.
1447 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) {
1448 isl_map_free(LoadAccs);
1449 isl_map_free(StoreAccs);
1450 continue;
1451 }
1452
1453 // And check if the remaining for overlap with other memory accesses.
1454 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs);
1455 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain());
1456 isl_set *AllAccs = isl_map_range(AllAccsRel);
1457
1458 for (MemoryAccess *MA : MemAccs) {
1459 if (MA == CandidatePair.first || MA == CandidatePair.second)
1460 continue;
1461
1462 isl_map *AccRel =
1463 isl_map_intersect_domain(MA->getAccessRelation(), getDomain());
1464 isl_set *Accs = isl_map_range(AccRel);
1465
1466 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) {
1467 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs));
1468 Valid = Valid && isl_set_is_empty(OverlapAccs);
1469 isl_set_free(OverlapAccs);
1470 }
1471 }
1472
1473 isl_set_free(AllAccs);
1474 if (!Valid)
1475 continue;
1476
Johannes Doerfertf6183392014-07-01 20:52:51 +00001477 const LoadInst *Load =
1478 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction());
1479 MemoryAccess::ReductionType RT =
1480 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load);
1481
Johannes Doerferte58a0122014-06-27 20:31:28 +00001482 // If no overlapping access was found we mark the load and store as
1483 // reduction like.
Johannes Doerfertf6183392014-07-01 20:52:51 +00001484 CandidatePair.first->markAsReductionLike(RT);
1485 CandidatePair.second->markAsReductionLike(RT);
Johannes Doerferte58a0122014-06-27 20:31:28 +00001486 }
Tobias Grosser75805372011-04-29 06:27:02 +00001487}
1488
Tobias Grosser74394f02013-01-14 22:40:23 +00001489std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); }
Tobias Grosser75805372011-04-29 06:27:02 +00001490
Tobias Grosser54839312015-04-21 11:37:25 +00001491std::string ScopStmt::getScheduleStr() const {
Tobias Grosser808cd692015-07-14 09:33:13 +00001492 auto *S = getSchedule();
1493 auto Str = stringFromIslObj(S);
1494 isl_map_free(S);
1495 return Str;
Tobias Grosser75805372011-04-29 06:27:02 +00001496}
1497
Tobias Grosser74394f02013-01-14 22:40:23 +00001498unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001499
Tobias Grosserf567e1a2015-02-19 22:16:12 +00001500unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001501
Tobias Grosser75805372011-04-29 06:27:02 +00001502const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
1503
Hongbin Zheng27f3afb2011-04-30 03:26:51 +00001504const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
Sebastian Pop860e0212013-02-15 21:26:44 +00001505 return NestLoops[Dimension];
Tobias Grosser75805372011-04-29 06:27:02 +00001506}
1507
Tobias Grosser74394f02013-01-14 22:40:23 +00001508isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001509
Tobias Grosser4f663aa2015-03-30 11:52:59 +00001510__isl_give isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); }
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +00001511
Tobias Grosser6e6c7e02015-03-30 12:22:39 +00001512__isl_give isl_space *ScopStmt::getDomainSpace() const {
Tobias Grosser78d8a3d2012-01-17 20:34:23 +00001513 return isl_set_get_space(Domain);
1514}
1515
Tobias Grosser4f663aa2015-03-30 11:52:59 +00001516__isl_give isl_id *ScopStmt::getDomainId() const {
1517 return isl_set_get_tuple_id(Domain);
1518}
Tobias Grossercd95b772012-08-30 11:49:38 +00001519
Tobias Grosser10120182015-12-16 16:14:03 +00001520ScopStmt::~ScopStmt() { isl_set_free(Domain); }
Tobias Grosser75805372011-04-29 06:27:02 +00001521
1522void ScopStmt::print(raw_ostream &OS) const {
1523 OS << "\t" << getBaseName() << "\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001524 OS.indent(12) << "Domain :=\n";
1525
1526 if (Domain) {
1527 OS.indent(16) << getDomainStr() << ";\n";
1528 } else
1529 OS.indent(16) << "n/a\n";
1530
Tobias Grosser54839312015-04-21 11:37:25 +00001531 OS.indent(12) << "Schedule :=\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001532
1533 if (Domain) {
Tobias Grosser54839312015-04-21 11:37:25 +00001534 OS.indent(16) << getScheduleStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001535 } else
1536 OS.indent(16) << "n/a\n";
1537
Tobias Grosser083d3d32014-06-28 08:59:45 +00001538 for (MemoryAccess *Access : MemAccs)
1539 Access->print(OS);
Tobias Grosser75805372011-04-29 06:27:02 +00001540}
1541
1542void ScopStmt::dump() const { print(dbgs()); }
1543
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001544void ScopStmt::removeMemoryAccesses(MemoryAccessList &InvMAs) {
Tobias Grosseref9ca5d2015-11-30 17:20:40 +00001545 // Remove all memory accesses in @p InvMAs from this statement
1546 // together with all scalar accesses that were caused by them.
Michael Krusead28e5a2016-01-26 13:33:15 +00001547 // MK_Value READs have no access instruction, hence would not be removed by
1548 // this function. However, it is only used for invariant LoadInst accesses,
1549 // its arguments are always affine, hence synthesizable, and therefore there
1550 // are no MK_Value READ accesses to be removed.
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00001551 for (MemoryAccess *MA : InvMAs) {
Tobias Grosseref9ca5d2015-11-30 17:20:40 +00001552 auto Predicate = [&](MemoryAccess *Acc) {
Tobias Grosser3a6ac9f2015-11-30 21:13:43 +00001553 return Acc->getAccessInstruction() == MA->getAccessInstruction();
Tobias Grosseref9ca5d2015-11-30 17:20:40 +00001554 };
1555 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate),
1556 MemAccs.end());
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00001557 InstructionToAccess.erase(MA->getAccessInstruction());
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00001558 }
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00001559}
1560
Tobias Grosser75805372011-04-29 06:27:02 +00001561//===----------------------------------------------------------------------===//
1562/// Scop class implement
Tobias Grosser60b54f12011-11-08 15:41:28 +00001563
Tobias Grosser7ffe4e82011-11-17 12:56:10 +00001564void Scop::setContext(__isl_take isl_set *NewContext) {
Tobias Grosserff9b54d2011-11-15 11:38:44 +00001565 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context));
1566 isl_set_free(Context);
1567 Context = NewContext;
1568}
1569
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001570/// @brief Remap parameter values but keep AddRecs valid wrt. invariant loads.
1571struct SCEVSensitiveParameterRewriter
1572 : public SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *> {
1573 ValueToValueMap &VMap;
1574 ScalarEvolution &SE;
1575
1576public:
1577 SCEVSensitiveParameterRewriter(ValueToValueMap &VMap, ScalarEvolution &SE)
1578 : VMap(VMap), SE(SE) {}
1579
1580 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE,
1581 ValueToValueMap &VMap) {
1582 SCEVSensitiveParameterRewriter SSPR(VMap, SE);
1583 return SSPR.visit(E);
1584 }
1585
1586 const SCEV *visit(const SCEV *E) {
1587 return SCEVVisitor<SCEVSensitiveParameterRewriter, const SCEV *>::visit(E);
1588 }
1589
1590 const SCEV *visitConstant(const SCEVConstant *E) { return E; }
1591
1592 const SCEV *visitTruncateExpr(const SCEVTruncateExpr *E) {
1593 return SE.getTruncateExpr(visit(E->getOperand()), E->getType());
1594 }
1595
1596 const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *E) {
1597 return SE.getZeroExtendExpr(visit(E->getOperand()), E->getType());
1598 }
1599
1600 const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *E) {
1601 return SE.getSignExtendExpr(visit(E->getOperand()), E->getType());
1602 }
1603
1604 const SCEV *visitAddExpr(const SCEVAddExpr *E) {
1605 SmallVector<const SCEV *, 4> Operands;
1606 for (int i = 0, e = E->getNumOperands(); i < e; ++i)
1607 Operands.push_back(visit(E->getOperand(i)));
1608 return SE.getAddExpr(Operands);
1609 }
1610
1611 const SCEV *visitMulExpr(const SCEVMulExpr *E) {
1612 SmallVector<const SCEV *, 4> Operands;
1613 for (int i = 0, e = E->getNumOperands(); i < e; ++i)
1614 Operands.push_back(visit(E->getOperand(i)));
1615 return SE.getMulExpr(Operands);
1616 }
1617
1618 const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) {
1619 SmallVector<const SCEV *, 4> Operands;
1620 for (int i = 0, e = E->getNumOperands(); i < e; ++i)
1621 Operands.push_back(visit(E->getOperand(i)));
1622 return SE.getSMaxExpr(Operands);
1623 }
1624
1625 const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) {
1626 SmallVector<const SCEV *, 4> Operands;
1627 for (int i = 0, e = E->getNumOperands(); i < e; ++i)
1628 Operands.push_back(visit(E->getOperand(i)));
1629 return SE.getUMaxExpr(Operands);
1630 }
1631
1632 const SCEV *visitUDivExpr(const SCEVUDivExpr *E) {
1633 return SE.getUDivExpr(visit(E->getLHS()), visit(E->getRHS()));
1634 }
1635
1636 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {
1637 auto *Start = visit(E->getStart());
1638 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
1639 visit(E->getStepRecurrence(SE)),
1640 E->getLoop(), SCEV::FlagAnyWrap);
1641 return SE.getAddExpr(Start, AddRec);
1642 }
1643
1644 const SCEV *visitUnknown(const SCEVUnknown *E) {
1645 if (auto *NewValue = VMap.lookup(E->getValue()))
1646 return SE.getUnknown(NewValue);
1647 return E;
1648 }
1649};
1650
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001651const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *S) {
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001652 return SCEVSensitiveParameterRewriter::rewrite(S, *SE, InvEquivClassVMap);
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001653}
1654
Tobias Grosserabfbe632013-02-05 12:09:06 +00001655void Scop::addParams(std::vector<const SCEV *> NewParameters) {
Tobias Grosser083d3d32014-06-28 08:59:45 +00001656 for (const SCEV *Parameter : NewParameters) {
Johannes Doerfertbe409962015-03-29 20:45:09 +00001657 Parameter = extractConstantFactor(Parameter, *SE).second;
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001658
1659 // Normalize the SCEV to get the representing element for an invariant load.
1660 Parameter = getRepresentingInvariantLoadSCEV(Parameter);
1661
Tobias Grosser60b54f12011-11-08 15:41:28 +00001662 if (ParameterIds.find(Parameter) != ParameterIds.end())
1663 continue;
1664
1665 int dimension = Parameters.size();
1666
1667 Parameters.push_back(Parameter);
1668 ParameterIds[Parameter] = dimension;
1669 }
1670}
1671
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001672__isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) {
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001673 // Normalize the SCEV to get the representing element for an invariant load.
1674 Parameter = getRepresentingInvariantLoadSCEV(Parameter);
1675
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001676 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter);
Tobias Grosser76c2e322011-11-07 12:58:59 +00001677
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001678 if (IdIter == ParameterIds.end())
Tobias Grosser5a56cbf2014-04-16 07:33:47 +00001679 return nullptr;
Tobias Grosser76c2e322011-11-07 12:58:59 +00001680
Tobias Grosser8f99c162011-11-15 11:38:55 +00001681 std::string ParameterName;
1682
Craig Topper7fb6e472016-01-31 20:36:20 +00001683 ParameterName = "p_" + utostr(IdIter->second);
Tobias Grosserb39c96a2015-11-17 11:54:51 +00001684
Tobias Grosser8f99c162011-11-15 11:38:55 +00001685 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1686 Value *Val = ValueParameter->getValue();
Tobias Grosser8f99c162011-11-15 11:38:55 +00001687
Tobias Grosserb39c96a2015-11-17 11:54:51 +00001688 // If this parameter references a specific Value and this value has a name
1689 // we use this name as it is likely to be unique and more useful than just
1690 // a number.
1691 if (Val->hasName())
1692 ParameterName = Val->getName();
1693 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) {
1694 auto LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets();
1695 if (LoadOrigin->hasName()) {
1696 ParameterName += "_loaded_from_";
1697 ParameterName +=
1698 LI->getPointerOperand()->stripInBoundsOffsets()->getName();
1699 }
1700 }
1701 }
Tobias Grosser8f99c162011-11-15 11:38:55 +00001702
Tobias Grosser20532b82014-04-11 17:56:49 +00001703 return isl_id_alloc(getIslCtx(), ParameterName.c_str(),
1704 const_cast<void *>((const void *)Parameter));
Tobias Grosser76c2e322011-11-07 12:58:59 +00001705}
Tobias Grosser75805372011-04-29 06:27:02 +00001706
Johannes Doerfert5d5b3062015-08-20 18:06:30 +00001707isl_set *Scop::addNonEmptyDomainConstraints(isl_set *C) const {
1708 isl_set *DomainContext = isl_union_set_params(getDomains());
1709 return isl_set_intersect_params(C, DomainContext);
1710}
1711
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001712void Scop::buildBoundaryContext() {
Tobias Grosser4927c8e2015-11-24 12:50:02 +00001713 if (IgnoreIntegerWrapping) {
1714 BoundaryContext = isl_set_universe(getParamSpace());
1715 return;
1716 }
1717
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001718 BoundaryContext = Affinator.getWrappingContext();
Tobias Grosser4cd07b12015-11-11 17:34:02 +00001719
1720 // The isl_set_complement operation used to create the boundary context
1721 // can possibly become very expensive. We bound the compile time of
1722 // this operation by setting a compute out.
1723 //
1724 // TODO: We can probably get around using isl_set_complement and directly
1725 // AST generate BoundaryContext.
1726 long MaxOpsOld = isl_ctx_get_max_operations(getIslCtx());
Tobias Grosserf920fb12015-11-13 16:56:13 +00001727 isl_ctx_reset_operations(getIslCtx());
Tobias Grosser4cd07b12015-11-11 17:34:02 +00001728 isl_ctx_set_max_operations(getIslCtx(), 300000);
1729 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_CONTINUE);
1730
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001731 BoundaryContext = isl_set_complement(BoundaryContext);
Tobias Grosser4cd07b12015-11-11 17:34:02 +00001732
Tobias Grossera52b4da2015-11-11 17:59:53 +00001733 if (isl_ctx_last_error(getIslCtx()) == isl_error_quota) {
1734 isl_set_free(BoundaryContext);
Tobias Grosser4cd07b12015-11-11 17:34:02 +00001735 BoundaryContext = isl_set_empty(getParamSpace());
Tobias Grossera52b4da2015-11-11 17:59:53 +00001736 }
Tobias Grosser4cd07b12015-11-11 17:34:02 +00001737
1738 isl_options_set_on_error(getIslCtx(), ISL_ON_ERROR_ABORT);
1739 isl_ctx_reset_operations(getIslCtx());
1740 isl_ctx_set_max_operations(getIslCtx(), MaxOpsOld);
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001741 BoundaryContext = isl_set_gist_params(BoundaryContext, getContext());
Johannes Doerfertd84493e2015-11-12 02:33:38 +00001742 trackAssumption(WRAPPING, BoundaryContext, DebugLoc());
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001743}
1744
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001745void Scop::addUserAssumptions(AssumptionCache &AC) {
1746 auto *R = &getRegion();
1747 auto &F = *R->getEntry()->getParent();
1748 for (auto &Assumption : AC.assumptions()) {
1749 auto *CI = dyn_cast_or_null<CallInst>(Assumption);
1750 if (!CI || CI->getNumArgOperands() != 1)
1751 continue;
1752 if (!DT.dominates(CI->getParent(), R->getEntry()))
1753 continue;
1754
1755 auto *Val = CI->getArgOperand(0);
1756 std::vector<const SCEV *> Params;
1757 if (!isAffineParamConstraint(Val, R, *SE, Params)) {
1758 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F,
1759 CI->getDebugLoc(),
1760 "Non-affine user assumption ignored.");
1761 continue;
1762 }
1763
1764 addParams(Params);
1765
1766 auto *L = LI.getLoopFor(CI->getParent());
1767 SmallVector<isl_set *, 2> ConditionSets;
1768 buildConditionSets(*this, Val, nullptr, L, Context, ConditionSets);
1769 assert(ConditionSets.size() == 2);
1770 isl_set_free(ConditionSets[1]);
1771
1772 auto *AssumptionCtx = ConditionSets[0];
1773 emitOptimizationRemarkAnalysis(
1774 F.getContext(), DEBUG_TYPE, F, CI->getDebugLoc(),
1775 "Use user assumption: " + stringFromIslObj(AssumptionCtx));
1776 Context = isl_set_intersect(Context, AssumptionCtx);
1777 }
1778}
1779
Tobias Grosser8a9c2352015-08-16 10:19:29 +00001780void Scop::addUserContext() {
1781 if (UserContextStr.empty())
1782 return;
1783
1784 isl_set *UserContext = isl_set_read_from_str(IslCtx, UserContextStr.c_str());
1785 isl_space *Space = getParamSpace();
1786 if (isl_space_dim(Space, isl_dim_param) !=
1787 isl_set_dim(UserContext, isl_dim_param)) {
1788 auto SpaceStr = isl_space_to_str(Space);
1789 errs() << "Error: the context provided in -polly-context has not the same "
1790 << "number of dimensions than the computed context. Due to this "
1791 << "mismatch, the -polly-context option is ignored. Please provide "
1792 << "the context in the parameter space: " << SpaceStr << ".\n";
1793 free(SpaceStr);
1794 isl_set_free(UserContext);
1795 isl_space_free(Space);
1796 return;
1797 }
1798
1799 for (unsigned i = 0; i < isl_space_dim(Space, isl_dim_param); i++) {
1800 auto NameContext = isl_set_get_dim_name(Context, isl_dim_param, i);
1801 auto NameUserContext = isl_set_get_dim_name(UserContext, isl_dim_param, i);
1802
1803 if (strcmp(NameContext, NameUserContext) != 0) {
1804 auto SpaceStr = isl_space_to_str(Space);
1805 errs() << "Error: the name of dimension " << i
1806 << " provided in -polly-context "
1807 << "is '" << NameUserContext << "', but the name in the computed "
1808 << "context is '" << NameContext
1809 << "'. Due to this name mismatch, "
1810 << "the -polly-context option is ignored. Please provide "
1811 << "the context in the parameter space: " << SpaceStr << ".\n";
1812 free(SpaceStr);
1813 isl_set_free(UserContext);
1814 isl_space_free(Space);
1815 return;
1816 }
1817
1818 UserContext =
1819 isl_set_set_dim_id(UserContext, isl_dim_param, i,
1820 isl_space_get_dim_id(Space, isl_dim_param, i));
1821 }
1822
1823 Context = isl_set_intersect(Context, UserContext);
1824 isl_space_free(Space);
1825}
1826
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001827void Scop::buildInvariantEquivalenceClasses() {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001828 DenseMap<const SCEV *, LoadInst *> EquivClasses;
1829
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001830 const InvariantLoadsSetTy &RIL = *SD.getRequiredInvariantLoads(&getRegion());
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001831 for (LoadInst *LInst : RIL) {
1832 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
1833
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001834 LoadInst *&ClassRep = EquivClasses[PointerSCEV];
Johannes Doerfertfc4bfc42015-11-11 04:30:07 +00001835 if (ClassRep) {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00001836 InvEquivClassVMap[LInst] = ClassRep;
Johannes Doerfertfc4bfc42015-11-11 04:30:07 +00001837 continue;
1838 }
1839
1840 ClassRep = LInst;
1841 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList(),
1842 nullptr);
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001843 }
1844}
1845
Tobias Grosser6be480c2011-11-08 15:41:13 +00001846void Scop::buildContext() {
1847 isl_space *Space = isl_space_params_alloc(IslCtx, 0);
Tobias Grossere86109f2013-10-29 21:05:49 +00001848 Context = isl_set_universe(isl_space_copy(Space));
1849 AssumedContext = isl_set_universe(Space);
Tobias Grosser0e27e242011-10-06 00:03:48 +00001850}
1851
Tobias Grosser18daaca2012-05-22 10:47:27 +00001852void Scop::addParameterBounds() {
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001853 for (const auto &ParamID : ParameterIds) {
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001854 int dim = ParamID.second;
Tobias Grosser18daaca2012-05-22 10:47:27 +00001855
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001856 ConstantRange SRange = SE->getSignedRange(ParamID.first);
Tobias Grosser18daaca2012-05-22 10:47:27 +00001857
Johannes Doerferte7044942015-02-24 11:58:30 +00001858 Context = addRangeBoundsToSet(Context, SRange, dim, isl_dim_param);
Tobias Grosser18daaca2012-05-22 10:47:27 +00001859 }
1860}
1861
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001862void Scop::realignParams() {
Tobias Grosser6be480c2011-11-08 15:41:13 +00001863 // Add all parameters into a common model.
Tobias Grosser60b54f12011-11-08 15:41:28 +00001864 isl_space *Space = isl_space_params_alloc(IslCtx, ParameterIds.size());
Tobias Grosser6be480c2011-11-08 15:41:13 +00001865
Tobias Grosser083d3d32014-06-28 08:59:45 +00001866 for (const auto &ParamID : ParameterIds) {
1867 const SCEV *Parameter = ParamID.first;
Tobias Grosser6be480c2011-11-08 15:41:13 +00001868 isl_id *id = getIdForParam(Parameter);
Tobias Grosser083d3d32014-06-28 08:59:45 +00001869 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id);
Tobias Grosser6be480c2011-11-08 15:41:13 +00001870 }
1871
1872 // Align the parameters of all data structures to the model.
1873 Context = isl_set_align_params(Context, Space);
1874
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001875 for (ScopStmt &Stmt : *this)
1876 Stmt.realignParams();
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001877}
1878
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001879static __isl_give isl_set *
1880simplifyAssumptionContext(__isl_take isl_set *AssumptionContext,
1881 const Scop &S) {
Johannes Doerfertf85ad042015-11-08 20:16:39 +00001882 // If we modelt all blocks in the SCoP that have side effects we can simplify
1883 // the context with the constraints that are needed for anything to be
1884 // executed at all. However, if we have error blocks in the SCoP we already
1885 // assumed some parameter combinations cannot occure and removed them from the
1886 // domains, thus we cannot use the remaining domain to simplify the
1887 // assumptions.
1888 if (!S.hasErrorBlock()) {
1889 isl_set *DomainParameters = isl_union_set_params(S.getDomains());
1890 AssumptionContext =
1891 isl_set_gist_params(AssumptionContext, DomainParameters);
1892 }
1893
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001894 AssumptionContext = isl_set_gist_params(AssumptionContext, S.getContext());
1895 return AssumptionContext;
1896}
1897
1898void Scop::simplifyContexts() {
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001899 // The parameter constraints of the iteration domains give us a set of
1900 // constraints that need to hold for all cases where at least a single
1901 // statement iteration is executed in the whole scop. We now simplify the
1902 // assumed context under the assumption that such constraints hold and at
1903 // least a single statement iteration is executed. For cases where no
1904 // statement instances are executed, the assumptions we have taken about
1905 // the executed code do not matter and can be changed.
1906 //
1907 // WARNING: This only holds if the assumptions we have taken do not reduce
1908 // the set of statement instances that are executed. Otherwise we
1909 // may run into a case where the iteration domains suggest that
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001910 // for a certain set of parameter constraints no code is executed,
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001911 // but in the original program some computation would have been
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001912 // performed. In such a case, modifying the run-time conditions and
1913 // possibly influencing the run-time check may cause certain scops
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001914 // to not be executed.
1915 //
1916 // Example:
1917 //
1918 // When delinearizing the following code:
1919 //
1920 // for (long i = 0; i < 100; i++)
1921 // for (long j = 0; j < m; j++)
1922 // A[i+p][j] = 1.0;
1923 //
1924 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001925 // otherwise we would access out of bound data. Now, knowing that code is
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001926 // only executed for the case m >= 0, it is sufficient to assume p >= 0.
Johannes Doerfert883f8c12015-09-15 22:52:53 +00001927 AssumedContext = simplifyAssumptionContext(AssumedContext, *this);
1928 BoundaryContext = simplifyAssumptionContext(BoundaryContext, *this);
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001929}
1930
Johannes Doerfertb164c792014-09-18 11:17:17 +00001931/// @brief Add the minimal/maximal access in @p Set to @p User.
Tobias Grosserb2f39922015-05-28 13:32:11 +00001932static isl_stat buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00001933 Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User;
1934 isl_pw_multi_aff *MinPMA, *MaxPMA;
1935 isl_pw_aff *LastDimAff;
1936 isl_aff *OneAff;
1937 unsigned Pos;
1938
Johannes Doerfert9143d672014-09-27 11:02:39 +00001939 // Restrict the number of parameters involved in the access as the lexmin/
1940 // lexmax computation will take too long if this number is high.
1941 //
1942 // Experiments with a simple test case using an i7 4800MQ:
1943 //
1944 // #Parameters involved | Time (in sec)
1945 // 6 | 0.01
1946 // 7 | 0.04
1947 // 8 | 0.12
1948 // 9 | 0.40
1949 // 10 | 1.54
1950 // 11 | 6.78
1951 // 12 | 30.38
1952 //
1953 if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) {
1954 unsigned InvolvedParams = 0;
1955 for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++)
1956 if (isl_set_involves_dims(Set, isl_dim_param, u, 1))
1957 InvolvedParams++;
1958
1959 if (InvolvedParams > RunTimeChecksMaxParameters) {
1960 isl_set_free(Set);
Tobias Grosserb2f39922015-05-28 13:32:11 +00001961 return isl_stat_error;
Johannes Doerfert9143d672014-09-27 11:02:39 +00001962 }
1963 }
1964
Johannes Doerfertb6755bb2015-02-14 12:00:06 +00001965 Set = isl_set_remove_divs(Set);
1966
Johannes Doerfertb164c792014-09-18 11:17:17 +00001967 MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set));
1968 MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set));
1969
Johannes Doerfert219b20e2014-10-07 14:37:59 +00001970 MinPMA = isl_pw_multi_aff_coalesce(MinPMA);
1971 MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA);
1972
Johannes Doerfertb164c792014-09-18 11:17:17 +00001973 // Adjust the last dimension of the maximal access by one as we want to
1974 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer
1975 // we test during code generation might now point after the end of the
1976 // allocated array but we will never dereference it anyway.
1977 assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) &&
1978 "Assumed at least one output dimension");
1979 Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1;
1980 LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos);
1981 OneAff = isl_aff_zero_on_domain(
1982 isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff)));
1983 OneAff = isl_aff_add_constant_si(OneAff, 1);
1984 LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff));
1985 MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff);
1986
1987 MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA));
1988
1989 isl_set_free(Set);
Tobias Grosserb2f39922015-05-28 13:32:11 +00001990 return isl_stat_ok;
Johannes Doerfertb164c792014-09-18 11:17:17 +00001991}
1992
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001993static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) {
1994 isl_set *Domain = MA->getStatement()->getDomain();
1995 Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain));
1996 return isl_set_reset_tuple_id(Domain);
1997}
1998
Johannes Doerfert338b42c2015-07-23 17:04:54 +00001999/// @brief Wrapper function to calculate minimal/maximal accesses to each array.
2000static bool calculateMinMaxAccess(__isl_take isl_union_map *Accesses,
Tobias Grosserbb853c22015-07-25 12:31:03 +00002001 __isl_take isl_union_set *Domains,
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002002 Scop::MinMaxVectorTy &MinMaxAccesses) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002003
2004 Accesses = isl_union_map_intersect_domain(Accesses, Domains);
2005 isl_union_set *Locations = isl_union_map_range(Accesses);
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002006 Locations = isl_union_set_coalesce(Locations);
2007 Locations = isl_union_set_detect_equalities(Locations);
2008 bool Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess,
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002009 &MinMaxAccesses));
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002010 isl_union_set_free(Locations);
2011 return Valid;
2012}
2013
Johannes Doerfert96425c22015-08-30 21:13:53 +00002014/// @brief Helper to treat non-affine regions and basic blocks the same.
2015///
2016///{
2017
2018/// @brief Return the block that is the representing block for @p RN.
2019static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) {
2020 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry()
2021 : RN->getNodeAs<BasicBlock>();
2022}
2023
2024/// @brief Return the @p idx'th block that is executed after @p RN.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002025static inline BasicBlock *
2026getRegionNodeSuccessor(RegionNode *RN, TerminatorInst *TI, unsigned idx) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002027 if (RN->isSubRegion()) {
2028 assert(idx == 0);
2029 return RN->getNodeAs<Region>()->getExit();
2030 }
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002031 return TI->getSuccessor(idx);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002032}
2033
2034/// @brief Return the smallest loop surrounding @p RN.
2035static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) {
2036 if (!RN->isSubRegion())
2037 return LI.getLoopFor(RN->getNodeAs<BasicBlock>());
2038
2039 Region *NonAffineSubRegion = RN->getNodeAs<Region>();
2040 Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry());
2041 while (L && NonAffineSubRegion->contains(L))
2042 L = L->getParentLoop();
2043 return L;
2044}
2045
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002046static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) {
2047 if (!RN->isSubRegion())
2048 return 1;
2049
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002050 Region *R = RN->getNodeAs<Region>();
Tobias Grosser0dd4a9a2016-02-01 01:55:08 +00002051 return std::distance(R->block_begin(), R->block_end());
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002052}
2053
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002054static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI,
2055 const DominatorTree &DT) {
Johannes Doerfertf5673802015-10-01 23:48:18 +00002056 if (!RN->isSubRegion())
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002057 return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT);
Johannes Doerfertf5673802015-10-01 23:48:18 +00002058 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002059 if (isErrorBlock(*BB, R, LI, DT))
Johannes Doerfertf5673802015-10-01 23:48:18 +00002060 return true;
2061 return false;
2062}
2063
Johannes Doerfert96425c22015-08-30 21:13:53 +00002064///}
2065
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002066static inline __isl_give isl_set *addDomainDimId(__isl_take isl_set *Domain,
2067 unsigned Dim, Loop *L) {
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002068 Domain = isl_set_lower_bound_si(Domain, isl_dim_set, Dim, -1);
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002069 isl_id *DimId =
2070 isl_id_alloc(isl_set_get_ctx(Domain), nullptr, static_cast<void *>(L));
2071 return isl_set_set_dim_id(Domain, isl_dim_set, Dim, DimId);
2072}
2073
Johannes Doerfert96425c22015-08-30 21:13:53 +00002074isl_set *Scop::getDomainConditions(ScopStmt *Stmt) {
2075 BasicBlock *BB = Stmt->isBlockStmt() ? Stmt->getBasicBlock()
2076 : Stmt->getRegion()->getEntry();
Johannes Doerfertcef616f2015-09-15 22:49:04 +00002077 return getDomainConditions(BB);
2078}
2079
2080isl_set *Scop::getDomainConditions(BasicBlock *BB) {
2081 assert(DomainMap.count(BB) && "Requested BB did not have a domain");
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002082 return isl_set_copy(DomainMap[BB]);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002083}
2084
Tobias Grosser9737c7b2015-11-22 11:06:51 +00002085void Scop::removeErrorBlockDomains() {
2086 auto removeDomains = [this](BasicBlock *Start) {
2087 auto BBNode = DT.getNode(Start);
2088 for (auto ErrorChild : depth_first(BBNode)) {
2089 auto ErrorChildBlock = ErrorChild->getBlock();
2090 auto CurrentDomain = DomainMap[ErrorChildBlock];
2091 auto Empty = isl_set_empty(isl_set_get_space(CurrentDomain));
2092 DomainMap[ErrorChildBlock] = Empty;
2093 isl_set_free(CurrentDomain);
2094 }
2095 };
2096
Tobias Grosser5ef2bc32015-11-23 10:18:23 +00002097 SmallVector<Region *, 4> Todo = {&R};
Tobias Grosser9737c7b2015-11-22 11:06:51 +00002098
2099 while (!Todo.empty()) {
2100 auto SubRegion = Todo.back();
2101 Todo.pop_back();
2102
2103 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) {
2104 for (auto &Child : *SubRegion)
2105 Todo.push_back(Child.get());
2106 continue;
2107 }
2108 if (containsErrorBlock(SubRegion->getNode(), getRegion(), LI, DT))
2109 removeDomains(SubRegion->getEntry());
2110 }
2111
2112 for (auto BB : R.blocks())
2113 if (isErrorBlock(*BB, R, LI, DT))
2114 removeDomains(BB);
2115}
2116
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002117void Scop::buildDomains(Region *R) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002118
Johannes Doerfert432658d2016-01-26 11:01:41 +00002119 bool IsOnlyNonAffineRegion = SD.isNonAffineSubRegion(R, R);
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002120 auto *EntryBB = R->getEntry();
Johannes Doerfert432658d2016-01-26 11:01:41 +00002121 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB);
2122 int LD = getRelativeLoopDepth(L);
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002123 auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx(), 0, LD + 1));
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002124
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002125 while (LD-- >= 0) {
2126 S = addDomainDimId(S, LD + 1, L);
2127 L = L->getParentLoop();
2128 }
2129
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002130 DomainMap[EntryBB] = S;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002131
Johannes Doerfert432658d2016-01-26 11:01:41 +00002132 if (IsOnlyNonAffineRegion)
Johannes Doerfert40fa56f2015-09-14 11:15:07 +00002133 return;
2134
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002135 buildDomainsWithBranchConstraints(R);
2136 propagateDomainConstraints(R);
Tobias Grosser9737c7b2015-11-22 11:06:51 +00002137
2138 // Error blocks and blocks dominated by them have been assumed to never be
2139 // executed. Representing them in the Scop does not add any value. In fact,
2140 // it is likely to cause issues during construction of the ScopStmts. The
2141 // contents of error blocks have not been verfied to be expressible and
2142 // will cause problems when building up a ScopStmt for them.
2143 // Furthermore, basic blocks dominated by error blocks may reference
2144 // instructions in the error block which, if the error block is not modeled,
2145 // can themselves not be constructed properly.
2146 removeErrorBlockDomains();
Johannes Doerfert96425c22015-08-30 21:13:53 +00002147}
2148
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002149void Scop::buildDomainsWithBranchConstraints(Region *R) {
Johannes Doerfert6f50c292016-01-26 11:03:25 +00002150 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion());
Johannes Doerfert96425c22015-08-30 21:13:53 +00002151
2152 // To create the domain for each block in R we iterate over all blocks and
2153 // subregions in R and propagate the conditions under which the current region
2154 // element is executed. To this end we iterate in reverse post order over R as
2155 // it ensures that we first visit all predecessors of a region node (either a
2156 // basic block or a subregion) before we visit the region node itself.
2157 // Initially, only the domain for the SCoP region entry block is set and from
2158 // there we propagate the current domain to all successors, however we add the
2159 // condition that the successor is actually executed next.
2160 // As we are only interested in non-loop carried constraints here we can
2161 // simply skip loop back edges.
2162
2163 ReversePostOrderTraversal<Region *> RTraversal(R);
2164 for (auto *RN : RTraversal) {
2165
2166 // Recurse for affine subregions but go on for basic blocks and non-affine
2167 // subregions.
2168 if (RN->isSubRegion()) {
2169 Region *SubRegion = RN->getNodeAs<Region>();
2170 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) {
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002171 buildDomainsWithBranchConstraints(SubRegion);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002172 continue;
2173 }
2174 }
2175
Tobias Grosserb76cd3c2015-11-11 08:42:20 +00002176 if (containsErrorBlock(RN, getRegion(), LI, DT))
Johannes Doerfertf85ad042015-11-08 20:16:39 +00002177 HasErrorBlock = true;
Johannes Doerfertf5673802015-10-01 23:48:18 +00002178
Johannes Doerfert96425c22015-08-30 21:13:53 +00002179 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002180 TerminatorInst *TI = BB->getTerminator();
2181
Tobias Grosserb76cd3c2015-11-11 08:42:20 +00002182 if (isa<UnreachableInst>(TI))
2183 continue;
2184
Johannes Doerfertf5673802015-10-01 23:48:18 +00002185 isl_set *Domain = DomainMap.lookup(BB);
2186 if (!Domain) {
2187 DEBUG(dbgs() << "\tSkip: " << BB->getName()
2188 << ", it is only reachable from error blocks.\n");
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002189 continue;
2190 }
2191
Johannes Doerfert96425c22015-08-30 21:13:53 +00002192 DEBUG(dbgs() << "\tVisit: " << BB->getName() << " : " << Domain << "\n");
Johannes Doerfert96425c22015-08-30 21:13:53 +00002193
2194 Loop *BBLoop = getRegionNodeLoop(RN, LI);
2195 int BBLoopDepth = getRelativeLoopDepth(BBLoop);
2196
2197 // Build the condition sets for the successor nodes of the current region
2198 // node. If it is a non-affine subregion we will always execute the single
2199 // exit node, hence the single entry node domain is the condition set. For
2200 // basic blocks we use the helper function buildConditionSets.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002201 SmallVector<isl_set *, 8> ConditionSets;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002202 if (RN->isSubRegion())
2203 ConditionSets.push_back(isl_set_copy(Domain));
2204 else
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002205 buildConditionSets(*this, TI, BBLoop, Domain, ConditionSets);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002206
2207 // Now iterate over the successors and set their initial domain based on
2208 // their condition set. We skip back edges here and have to be careful when
2209 // we leave a loop not to keep constraints over a dimension that doesn't
2210 // exist anymore.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002211 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
Johannes Doerfert96425c22015-08-30 21:13:53 +00002212 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002213 isl_set *CondSet = ConditionSets[u];
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002214 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002215
2216 // Skip back edges.
2217 if (DT.dominates(SuccBB, BB)) {
2218 isl_set_free(CondSet);
2219 continue;
2220 }
2221
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002222 // Do not adjust the number of dimensions if we enter a boxed loop or are
2223 // in a non-affine subregion or if the surrounding loop stays the same.
Johannes Doerfert96425c22015-08-30 21:13:53 +00002224 Loop *SuccBBLoop = LI.getLoopFor(SuccBB);
Johannes Doerfert6f50c292016-01-26 11:03:25 +00002225 while (BoxedLoops.count(SuccBBLoop))
2226 SuccBBLoop = SuccBBLoop->getParentLoop();
Johannes Doerfert634909c2015-10-04 14:57:41 +00002227
2228 if (BBLoop != SuccBBLoop) {
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002229
2230 // Check if the edge to SuccBB is a loop entry or exit edge. If so
2231 // adjust the dimensionality accordingly. Lastly, if we leave a loop
2232 // and enter a new one we need to drop the old constraints.
2233 int SuccBBLoopDepth = getRelativeLoopDepth(SuccBBLoop);
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002234 unsigned LoopDepthDiff = std::abs(BBLoopDepth - SuccBBLoopDepth);
Tobias Grosser2df884f2015-09-01 18:17:41 +00002235 if (BBLoopDepth > SuccBBLoopDepth) {
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002236 CondSet = isl_set_project_out(CondSet, isl_dim_set,
2237 isl_set_n_dim(CondSet) - LoopDepthDiff,
2238 LoopDepthDiff);
Tobias Grosser2df884f2015-09-01 18:17:41 +00002239 } else if (SuccBBLoopDepth > BBLoopDepth) {
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002240 assert(LoopDepthDiff == 1);
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002241 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1);
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002242 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop);
Tobias Grosser2df884f2015-09-01 18:17:41 +00002243 } else if (BBLoopDepth >= 0) {
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002244 assert(LoopDepthDiff <= 1);
Tobias Grosser2df884f2015-09-01 18:17:41 +00002245 CondSet = isl_set_project_out(CondSet, isl_dim_set, BBLoopDepth, 1);
2246 CondSet = isl_set_add_dims(CondSet, isl_dim_set, 1);
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002247 CondSet = addDomainDimId(CondSet, SuccBBLoopDepth, SuccBBLoop);
Tobias Grosser2df884f2015-09-01 18:17:41 +00002248 }
Johannes Doerfert96425c22015-08-30 21:13:53 +00002249 }
2250
2251 // Set the domain for the successor or merge it with an existing domain in
2252 // case there are multiple paths (without loop back edges) to the
2253 // successor block.
2254 isl_set *&SuccDomain = DomainMap[SuccBB];
2255 if (!SuccDomain)
2256 SuccDomain = CondSet;
2257 else
2258 SuccDomain = isl_set_union(SuccDomain, CondSet);
2259
2260 SuccDomain = isl_set_coalesce(SuccDomain);
Tobias Grosser75dc40c2015-12-20 13:31:48 +00002261 if (isl_set_n_basic_set(SuccDomain) > MaxConjunctsInDomain) {
2262 auto *Empty = isl_set_empty(isl_set_get_space(SuccDomain));
2263 isl_set_free(SuccDomain);
2264 SuccDomain = Empty;
2265 invalidate(ERROR_DOMAINCONJUNCTS, DebugLoc());
2266 }
Johannes Doerfert634909c2015-10-04 14:57:41 +00002267 DEBUG(dbgs() << "\tSet SuccBB: " << SuccBB->getName() << " : "
2268 << SuccDomain << "\n");
Johannes Doerfert96425c22015-08-30 21:13:53 +00002269 }
2270 }
2271}
2272
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002273/// @brief Return the domain for @p BB wrt @p DomainMap.
2274///
2275/// This helper function will lookup @p BB in @p DomainMap but also handle the
2276/// case where @p BB is contained in a non-affine subregion using the region
2277/// tree obtained by @p RI.
2278static __isl_give isl_set *
2279getDomainForBlock(BasicBlock *BB, DenseMap<BasicBlock *, isl_set *> &DomainMap,
2280 RegionInfo &RI) {
2281 auto DIt = DomainMap.find(BB);
2282 if (DIt != DomainMap.end())
2283 return isl_set_copy(DIt->getSecond());
2284
2285 Region *R = RI.getRegionFor(BB);
2286 while (R->getEntry() == BB)
2287 R = R->getParent();
2288 return getDomainForBlock(R->getEntry(), DomainMap, RI);
2289}
2290
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002291void Scop::propagateDomainConstraints(Region *R) {
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002292 // Iterate over the region R and propagate the domain constrains from the
2293 // predecessors to the current node. In contrast to the
2294 // buildDomainsWithBranchConstraints function, this one will pull the domain
2295 // information from the predecessors instead of pushing it to the successors.
2296 // Additionally, we assume the domains to be already present in the domain
2297 // map here. However, we iterate again in reverse post order so we know all
2298 // predecessors have been visited before a block or non-affine subregion is
2299 // visited.
2300
2301 // The set of boxed loops (loops in non-affine subregions) for this SCoP.
2302 auto &BoxedLoops = *SD.getBoxedLoops(&getRegion());
2303
2304 ReversePostOrderTraversal<Region *> RTraversal(R);
2305 for (auto *RN : RTraversal) {
2306
2307 // Recurse for affine subregions but go on for basic blocks and non-affine
2308 // subregions.
2309 if (RN->isSubRegion()) {
2310 Region *SubRegion = RN->getNodeAs<Region>();
2311 if (!SD.isNonAffineSubRegion(SubRegion, &getRegion())) {
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002312 propagateDomainConstraints(SubRegion);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002313 continue;
2314 }
2315 }
2316
Johannes Doerfertf5673802015-10-01 23:48:18 +00002317 // Get the domain for the current block and check if it was initialized or
2318 // not. The only way it was not is if this block is only reachable via error
2319 // blocks, thus will not be executed under the assumptions we make. Such
2320 // blocks have to be skipped as their predecessors might not have domains
2321 // either. It would not benefit us to compute the domain anyway, only the
2322 // domains of the error blocks that are reachable from non-error blocks
2323 // are needed to generate assumptions.
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002324 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Johannes Doerfertf5673802015-10-01 23:48:18 +00002325 isl_set *&Domain = DomainMap[BB];
2326 if (!Domain) {
2327 DEBUG(dbgs() << "\tSkip: " << BB->getName()
2328 << ", it is only reachable from error blocks.\n");
2329 DomainMap.erase(BB);
2330 continue;
2331 }
2332 DEBUG(dbgs() << "\tVisit: " << BB->getName() << " : " << Domain << "\n");
2333
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002334 Loop *BBLoop = getRegionNodeLoop(RN, LI);
2335 int BBLoopDepth = getRelativeLoopDepth(BBLoop);
2336
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002337 isl_set *PredDom = isl_set_empty(isl_set_get_space(Domain));
2338 for (auto *PredBB : predecessors(BB)) {
2339
2340 // Skip backedges
2341 if (DT.dominates(BB, PredBB))
2342 continue;
2343
2344 isl_set *PredBBDom = nullptr;
2345
2346 // Handle the SCoP entry block with its outside predecessors.
2347 if (!getRegion().contains(PredBB))
2348 PredBBDom = isl_set_universe(isl_set_get_space(PredDom));
2349
2350 if (!PredBBDom) {
2351 // Determine the loop depth of the predecessor and adjust its domain to
2352 // the domain of the current block. This can mean we have to:
2353 // o) Drop a dimension if this block is the exit of a loop, not the
2354 // header of a new loop and the predecessor was part of the loop.
2355 // o) Add an unconstrainted new dimension if this block is the header
2356 // of a loop and the predecessor is not part of it.
2357 // o) Drop the information about the innermost loop dimension when the
2358 // predecessor and the current block are surrounded by different
2359 // loops in the same depth.
2360 PredBBDom = getDomainForBlock(PredBB, DomainMap, *R->getRegionInfo());
2361 Loop *PredBBLoop = LI.getLoopFor(PredBB);
2362 while (BoxedLoops.count(PredBBLoop))
2363 PredBBLoop = PredBBLoop->getParentLoop();
2364
2365 int PredBBLoopDepth = getRelativeLoopDepth(PredBBLoop);
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002366 unsigned LoopDepthDiff = std::abs(BBLoopDepth - PredBBLoopDepth);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002367 if (BBLoopDepth < PredBBLoopDepth)
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002368 PredBBDom = isl_set_project_out(
2369 PredBBDom, isl_dim_set, isl_set_n_dim(PredBBDom) - LoopDepthDiff,
2370 LoopDepthDiff);
2371 else if (PredBBLoopDepth < BBLoopDepth) {
2372 assert(LoopDepthDiff == 1);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002373 PredBBDom = isl_set_add_dims(PredBBDom, isl_dim_set, 1);
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002374 } else if (BBLoop != PredBBLoop && BBLoopDepth >= 0) {
2375 assert(LoopDepthDiff <= 1);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002376 PredBBDom = isl_set_drop_constraints_involving_dims(
2377 PredBBDom, isl_dim_set, BBLoopDepth, 1);
Johannes Doerfertf4fa9872015-09-10 15:53:59 +00002378 }
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002379 }
2380
2381 PredDom = isl_set_union(PredDom, PredBBDom);
2382 }
2383
2384 // Under the union of all predecessor conditions we can reach this block.
Johannes Doerfertb20f1512015-09-15 22:11:49 +00002385 Domain = isl_set_coalesce(isl_set_intersect(Domain, PredDom));
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002386
Johannes Doerfertf32f5f22015-09-28 01:30:37 +00002387 if (BBLoop && BBLoop->getHeader() == BB && getRegion().contains(BBLoop))
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002388 addLoopBoundsToHeaderDomain(BBLoop);
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002389
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002390 // Add assumptions for error blocks.
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002391 if (containsErrorBlock(RN, getRegion(), LI, DT)) {
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002392 IsOptimized = true;
2393 isl_set *DomPar = isl_set_params(isl_set_copy(Domain));
Johannes Doerfertd84493e2015-11-12 02:33:38 +00002394 addAssumption(ERRORBLOCK, isl_set_complement(DomPar),
2395 BB->getTerminator()->getDebugLoc());
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002396 }
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002397 }
2398}
2399
2400/// @brief Create a map from SetSpace -> SetSpace where the dimensions @p Dim
2401/// is incremented by one and all other dimensions are equal, e.g.,
2402/// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3]
2403/// if @p Dim is 2 and @p SetSpace has 4 dimensions.
2404static __isl_give isl_map *
2405createNextIterationMap(__isl_take isl_space *SetSpace, unsigned Dim) {
2406 auto *MapSpace = isl_space_map_from_set(SetSpace);
2407 auto *NextIterationMap = isl_map_universe(isl_space_copy(MapSpace));
2408 for (unsigned u = 0; u < isl_map_n_in(NextIterationMap); u++)
2409 if (u != Dim)
2410 NextIterationMap =
2411 isl_map_equate(NextIterationMap, isl_dim_in, u, isl_dim_out, u);
2412 auto *C = isl_constraint_alloc_equality(isl_local_space_from_space(MapSpace));
2413 C = isl_constraint_set_constant_si(C, 1);
2414 C = isl_constraint_set_coefficient_si(C, isl_dim_in, Dim, 1);
2415 C = isl_constraint_set_coefficient_si(C, isl_dim_out, Dim, -1);
2416 NextIterationMap = isl_map_add_constraint(NextIterationMap, C);
2417 return NextIterationMap;
2418}
2419
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002420void Scop::addLoopBoundsToHeaderDomain(Loop *L) {
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002421 int LoopDepth = getRelativeLoopDepth(L);
2422 assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002423
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002424 BasicBlock *HeaderBB = L->getHeader();
2425 assert(DomainMap.count(HeaderBB));
2426 isl_set *&HeaderBBDom = DomainMap[HeaderBB];
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002427
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002428 isl_map *NextIterationMap =
2429 createNextIterationMap(isl_set_get_space(HeaderBBDom), LoopDepth);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002430
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002431 isl_set *UnionBackedgeCondition =
2432 isl_set_empty(isl_set_get_space(HeaderBBDom));
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002433
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002434 SmallVector<llvm::BasicBlock *, 4> LatchBlocks;
2435 L->getLoopLatches(LatchBlocks);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002436
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002437 for (BasicBlock *LatchBB : LatchBlocks) {
Johannes Doerfertf5673802015-10-01 23:48:18 +00002438
2439 // If the latch is only reachable via error statements we skip it.
2440 isl_set *LatchBBDom = DomainMap.lookup(LatchBB);
2441 if (!LatchBBDom)
2442 continue;
2443
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002444 isl_set *BackedgeCondition = nullptr;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002445
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002446 TerminatorInst *TI = LatchBB->getTerminator();
2447 BranchInst *BI = dyn_cast<BranchInst>(TI);
2448 if (BI && BI->isUnconditional())
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002449 BackedgeCondition = isl_set_copy(LatchBBDom);
2450 else {
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002451 SmallVector<isl_set *, 8> ConditionSets;
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002452 int idx = BI->getSuccessor(0) != HeaderBB;
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002453 buildConditionSets(*this, TI, L, LatchBBDom, ConditionSets);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002454
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002455 // Free the non back edge condition set as we do not need it.
2456 isl_set_free(ConditionSets[1 - idx]);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002457
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002458 BackedgeCondition = ConditionSets[idx];
Johannes Doerfert06c57b52015-09-20 15:00:20 +00002459 }
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002460
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002461 int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
2462 assert(LatchLoopDepth >= LoopDepth);
2463 BackedgeCondition =
2464 isl_set_project_out(BackedgeCondition, isl_dim_set, LoopDepth + 1,
2465 LatchLoopDepth - LoopDepth);
2466 UnionBackedgeCondition =
2467 isl_set_union(UnionBackedgeCondition, BackedgeCondition);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002468 }
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002469
2470 isl_map *ForwardMap = isl_map_lex_le(isl_set_get_space(HeaderBBDom));
2471 for (int i = 0; i < LoopDepth; i++)
2472 ForwardMap = isl_map_equate(ForwardMap, isl_dim_in, i, isl_dim_out, i);
2473
2474 isl_set *UnionBackedgeConditionComplement =
2475 isl_set_complement(UnionBackedgeCondition);
2476 UnionBackedgeConditionComplement = isl_set_lower_bound_si(
2477 UnionBackedgeConditionComplement, isl_dim_set, LoopDepth, 0);
2478 UnionBackedgeConditionComplement =
2479 isl_set_apply(UnionBackedgeConditionComplement, ForwardMap);
2480 HeaderBBDom = isl_set_subtract(HeaderBBDom, UnionBackedgeConditionComplement);
2481 HeaderBBDom = isl_set_apply(HeaderBBDom, NextIterationMap);
2482
2483 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
2484 HeaderBBDom = Parts.second;
2485
Johannes Doerfert6a72a2a2015-09-20 16:59:23 +00002486 // Check if there is a <nsw> tagged AddRec for this loop and if so do not add
2487 // the bounded assumptions to the context as they are already implied by the
2488 // <nsw> tag.
2489 if (Affinator.hasNSWAddRecForLoop(L)) {
2490 isl_set_free(Parts.first);
2491 return;
2492 }
2493
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002494 isl_set *UnboundedCtx = isl_set_params(Parts.first);
2495 isl_set *BoundedCtx = isl_set_complement(UnboundedCtx);
Johannes Doerfertd84493e2015-11-12 02:33:38 +00002496 addAssumption(INFINITELOOP, BoundedCtx,
2497 HeaderBB->getTerminator()->getDebugLoc());
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002498}
2499
Johannes Doerfert120de4b2015-08-20 18:30:08 +00002500void Scop::buildAliasChecks(AliasAnalysis &AA) {
2501 if (!PollyUseRuntimeAliasChecks)
2502 return;
2503
2504 if (buildAliasGroups(AA))
2505 return;
2506
2507 // If a problem occurs while building the alias groups we need to delete
2508 // this SCoP and pretend it wasn't valid in the first place. To this end
2509 // we make the assumed context infeasible.
Tobias Grosser8d4f6262015-12-12 09:52:26 +00002510 invalidate(ALIASING, DebugLoc());
Johannes Doerfert120de4b2015-08-20 18:30:08 +00002511
2512 DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << getNameStr()
2513 << " could not be created as the number of parameters involved "
2514 "is too high. The SCoP will be "
2515 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust "
2516 "the maximal number of parameters but be advised that the "
2517 "compile time might increase exponentially.\n\n");
2518}
2519
Johannes Doerfert9143d672014-09-27 11:02:39 +00002520bool Scop::buildAliasGroups(AliasAnalysis &AA) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00002521 // To create sound alias checks we perform the following steps:
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002522 // o) Use the alias analysis and an alias set tracker to build alias sets
Johannes Doerfertb164c792014-09-18 11:17:17 +00002523 // for all memory accesses inside the SCoP.
2524 // o) For each alias set we then map the aliasing pointers back to the
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002525 // memory accesses we know, thus obtain groups of memory accesses which
Johannes Doerfertb164c792014-09-18 11:17:17 +00002526 // might alias.
Johannes Doerferteeab05a2014-10-01 12:42:37 +00002527 // o) We divide each group based on the domains of the minimal/maximal
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002528 // accesses. That means two minimal/maximal accesses are only in a group
Johannes Doerferteeab05a2014-10-01 12:42:37 +00002529 // if their access domains intersect, otherwise they are in different
2530 // ones.
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002531 // o) We partition each group into read only and non read only accesses.
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002532 // o) For each group with more than one base pointer we then compute minimal
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002533 // and maximal accesses to each array of a group in read only and non
2534 // read only partitions separately.
Johannes Doerfertb164c792014-09-18 11:17:17 +00002535 using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
2536
2537 AliasSetTracker AST(AA);
2538
2539 DenseMap<Value *, MemoryAccess *> PtrToAcc;
Johannes Doerfert13771732014-10-01 12:40:46 +00002540 DenseSet<Value *> HasWriteAccess;
Tobias Grosser7c3bad52015-05-27 05:16:57 +00002541 for (ScopStmt &Stmt : *this) {
Johannes Doerfertf1ee2622014-10-06 17:43:00 +00002542
2543 // Skip statements with an empty domain as they will never be executed.
Tobias Grosser7c3bad52015-05-27 05:16:57 +00002544 isl_set *StmtDomain = Stmt.getDomain();
Johannes Doerfertf1ee2622014-10-06 17:43:00 +00002545 bool StmtDomainEmpty = isl_set_is_empty(StmtDomain);
2546 isl_set_free(StmtDomain);
2547 if (StmtDomainEmpty)
2548 continue;
2549
Tobias Grosser7c3bad52015-05-27 05:16:57 +00002550 for (MemoryAccess *MA : Stmt) {
Tobias Grossera535dff2015-12-13 19:59:01 +00002551 if (MA->isScalarKind())
Johannes Doerfertb164c792014-09-18 11:17:17 +00002552 continue;
Johannes Doerfert13771732014-10-01 12:40:46 +00002553 if (!MA->isRead())
2554 HasWriteAccess.insert(MA->getBaseAddr());
Michael Kruse70131d32016-01-27 17:09:17 +00002555 MemAccInst Acc(MA->getAccessInstruction());
2556 PtrToAcc[Acc.getPointerOperand()] = MA;
Johannes Doerfertb164c792014-09-18 11:17:17 +00002557 AST.add(Acc);
2558 }
2559 }
2560
2561 SmallVector<AliasGroupTy, 4> AliasGroups;
2562 for (AliasSet &AS : AST) {
Johannes Doerfert74f68692014-10-08 02:23:48 +00002563 if (AS.isMustAlias() || AS.isForwardingAliasSet())
Johannes Doerfertb164c792014-09-18 11:17:17 +00002564 continue;
2565 AliasGroupTy AG;
2566 for (auto PR : AS)
2567 AG.push_back(PtrToAcc[PR.getValue()]);
2568 assert(AG.size() > 1 &&
2569 "Alias groups should contain at least two accesses");
2570 AliasGroups.push_back(std::move(AG));
2571 }
2572
Johannes Doerferteeab05a2014-10-01 12:42:37 +00002573 // Split the alias groups based on their domain.
2574 for (unsigned u = 0; u < AliasGroups.size(); u++) {
2575 AliasGroupTy NewAG;
2576 AliasGroupTy &AG = AliasGroups[u];
2577 AliasGroupTy::iterator AGI = AG.begin();
2578 isl_set *AGDomain = getAccessDomain(*AGI);
2579 while (AGI != AG.end()) {
2580 MemoryAccess *MA = *AGI;
2581 isl_set *MADomain = getAccessDomain(MA);
2582 if (isl_set_is_disjoint(AGDomain, MADomain)) {
2583 NewAG.push_back(MA);
2584 AGI = AG.erase(AGI);
2585 isl_set_free(MADomain);
2586 } else {
2587 AGDomain = isl_set_union(AGDomain, MADomain);
2588 AGI++;
2589 }
2590 }
2591 if (NewAG.size() > 1)
2592 AliasGroups.push_back(std::move(NewAG));
2593 isl_set_free(AGDomain);
2594 }
2595
Johannes Doerfert0cf4e0a2015-11-12 02:32:51 +00002596 auto &F = *getRegion().getEntry()->getParent();
Tobias Grosserf4c24b22015-04-05 13:11:54 +00002597 MapVector<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs;
Johannes Doerfert13771732014-10-01 12:40:46 +00002598 SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues;
2599 for (AliasGroupTy &AG : AliasGroups) {
2600 NonReadOnlyBaseValues.clear();
2601 ReadOnlyPairs.clear();
2602
Johannes Doerferteeab05a2014-10-01 12:42:37 +00002603 if (AG.size() < 2) {
2604 AG.clear();
2605 continue;
2606 }
2607
Johannes Doerfert13771732014-10-01 12:40:46 +00002608 for (auto II = AG.begin(); II != AG.end();) {
Johannes Doerfert0cf4e0a2015-11-12 02:32:51 +00002609 emitOptimizationRemarkAnalysis(
2610 F.getContext(), DEBUG_TYPE, F,
2611 (*II)->getAccessInstruction()->getDebugLoc(),
2612 "Possibly aliasing pointer, use restrict keyword.");
2613
Johannes Doerfert13771732014-10-01 12:40:46 +00002614 Value *BaseAddr = (*II)->getBaseAddr();
2615 if (HasWriteAccess.count(BaseAddr)) {
2616 NonReadOnlyBaseValues.insert(BaseAddr);
2617 II++;
2618 } else {
2619 ReadOnlyPairs[BaseAddr].insert(*II);
2620 II = AG.erase(II);
2621 }
2622 }
2623
2624 // If we don't have read only pointers check if there are at least two
2625 // non read only pointers, otherwise clear the alias group.
Tobias Grosserbb853c22015-07-25 12:31:03 +00002626 if (ReadOnlyPairs.empty() && NonReadOnlyBaseValues.size() <= 1) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002627 AG.clear();
Johannes Doerfert13771732014-10-01 12:40:46 +00002628 continue;
2629 }
2630
2631 // If we don't have non read only pointers clear the alias group.
2632 if (NonReadOnlyBaseValues.empty()) {
2633 AG.clear();
2634 continue;
2635 }
2636
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002637 // Calculate minimal and maximal accesses for non read only accesses.
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002638 MinMaxAliasGroups.emplace_back();
2639 MinMaxVectorPairTy &pair = MinMaxAliasGroups.back();
2640 MinMaxVectorTy &MinMaxAccessesNonReadOnly = pair.first;
2641 MinMaxVectorTy &MinMaxAccessesReadOnly = pair.second;
2642 MinMaxAccessesNonReadOnly.reserve(AG.size());
Johannes Doerfertb164c792014-09-18 11:17:17 +00002643
2644 isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002645
2646 // AG contains only non read only accesses.
Johannes Doerfertb164c792014-09-18 11:17:17 +00002647 for (MemoryAccess *MA : AG)
2648 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
Johannes Doerfertb164c792014-09-18 11:17:17 +00002649
Tobias Grosserdaaed0e2015-08-20 21:29:26 +00002650 bool Valid = calculateMinMaxAccess(Accesses, getDomains(),
2651 MinMaxAccessesNonReadOnly);
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002652
2653 // Bail out if the number of values we need to compare is too large.
2654 // This is important as the number of comparisions grows quadratically with
2655 // the number of values we need to compare.
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002656 if (!Valid || (MinMaxAccessesNonReadOnly.size() + !ReadOnlyPairs.empty() >
2657 RunTimeChecksMaxArraysPerGroup))
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002658 return false;
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002659
2660 // Calculate minimal and maximal accesses for read only accesses.
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002661 MinMaxAccessesReadOnly.reserve(ReadOnlyPairs.size());
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002662 Accesses = isl_union_map_empty(getParamSpace());
2663
2664 for (const auto &ReadOnlyPair : ReadOnlyPairs)
2665 for (MemoryAccess *MA : ReadOnlyPair.second)
2666 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
2667
Tobias Grosserdaaed0e2015-08-20 21:29:26 +00002668 Valid =
2669 calculateMinMaxAccess(Accesses, getDomains(), MinMaxAccessesReadOnly);
Johannes Doerfert9143d672014-09-27 11:02:39 +00002670
2671 if (!Valid)
Tobias Grosser50d4e2e2015-03-28 14:50:32 +00002672 return false;
Johannes Doerfertb164c792014-09-18 11:17:17 +00002673 }
Johannes Doerfert9143d672014-09-27 11:02:39 +00002674
Tobias Grosser50d4e2e2015-03-28 14:50:32 +00002675 return true;
Johannes Doerfertb164c792014-09-18 11:17:17 +00002676}
2677
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002678/// @brief Get the smallest loop that contains @p R but is not in @p R.
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002679static Loop *getLoopSurroundingRegion(Region &R, LoopInfo &LI) {
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002680 // Start with the smallest loop containing the entry and expand that
2681 // loop until it contains all blocks in the region. If there is a loop
2682 // containing all blocks in the region check if it is itself contained
2683 // and if so take the parent loop as it will be the smallest containing
2684 // the region but not contained by it.
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002685 Loop *L = LI.getLoopFor(R.getEntry());
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002686 while (L) {
2687 bool AllContained = true;
2688 for (auto *BB : R.blocks())
2689 AllContained &= L->contains(BB);
2690 if (AllContained)
2691 break;
2692 L = L->getParentLoop();
2693 }
2694
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002695 return L ? (R.contains(L) ? L->getParentLoop() : L) : nullptr;
2696}
2697
Johannes Doerfertf8206cf2015-04-12 22:58:40 +00002698static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI,
2699 ScopDetection &SD) {
2700
2701 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD.getBoxedLoops(&R);
2702
Johannes Doerferte3da05a2014-11-01 00:12:13 +00002703 unsigned MinLD = INT_MAX, MaxLD = 0;
2704 for (BasicBlock *BB : R.blocks()) {
2705 if (Loop *L = LI.getLoopFor(BB)) {
David Peixottodc0a11c2015-01-13 18:31:55 +00002706 if (!R.contains(L))
2707 continue;
Johannes Doerfertf8206cf2015-04-12 22:58:40 +00002708 if (BoxedLoops && BoxedLoops->count(L))
2709 continue;
Johannes Doerferte3da05a2014-11-01 00:12:13 +00002710 unsigned LD = L->getLoopDepth();
2711 MinLD = std::min(MinLD, LD);
2712 MaxLD = std::max(MaxLD, LD);
2713 }
2714 }
2715
2716 // Handle the case that there is no loop in the SCoP first.
2717 if (MaxLD == 0)
2718 return 1;
2719
2720 assert(MinLD >= 1 && "Minimal loop depth should be at least one");
2721 assert(MaxLD >= MinLD &&
2722 "Maximal loop depth was smaller than mininaml loop depth?");
2723 return MaxLD - MinLD + 1;
2724}
2725
Johannes Doerfert478a7de2015-10-02 13:09:31 +00002726Scop::Scop(Region &R, AccFuncMapType &AccFuncMap, ScopDetection &SD,
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002727 ScalarEvolution &ScalarEvolution, DominatorTree &DT, LoopInfo &LI,
Johannes Doerfert96425c22015-08-30 21:13:53 +00002728 isl_ctx *Context, unsigned MaxLoopDepth)
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002729 : LI(LI), DT(DT), SE(&ScalarEvolution), SD(SD), R(R),
2730 AccFuncMap(AccFuncMap), IsOptimized(false),
Johannes Doerfertf85ad042015-11-08 20:16:39 +00002731 HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false),
2732 MaxLoopDepth(MaxLoopDepth), IslCtx(Context), Context(nullptr),
2733 Affinator(this), AssumedContext(nullptr), BoundaryContext(nullptr),
Tobias Grosserd840fc72016-02-04 13:18:42 +00002734 Schedule(nullptr) {
2735 buildContext();
2736}
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002737
Johannes Doerfert2af10e22015-11-12 03:25:01 +00002738void Scop::init(AliasAnalysis &AA, AssumptionCache &AC) {
Johannes Doerfert2af10e22015-11-12 03:25:01 +00002739 addUserAssumptions(AC);
Johannes Doerfert697fdf82015-10-09 17:12:26 +00002740 buildInvariantEquivalenceClasses();
2741
Johannes Doerfertd8dd8632015-10-07 20:31:36 +00002742 buildDomains(&R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002743
Michael Krusecac948e2015-10-02 13:53:07 +00002744 // Remove empty and ignored statements.
Michael Kruseafe06702015-10-02 16:33:27 +00002745 // Exit early in case there are no executable statements left in this scop.
Michael Krusecac948e2015-10-02 13:53:07 +00002746 simplifySCoP(true);
Michael Kruseafe06702015-10-02 16:33:27 +00002747 if (Stmts.empty())
2748 return;
Tobias Grosser75805372011-04-29 06:27:02 +00002749
Michael Krusecac948e2015-10-02 13:53:07 +00002750 // The ScopStmts now have enough information to initialize themselves.
2751 for (ScopStmt &Stmt : Stmts)
2752 Stmt.init();
2753
Johannes Doerfertf9711ef2016-01-06 12:59:23 +00002754 buildSchedule();
Tobias Grosser75805372011-04-29 06:27:02 +00002755
Tobias Grosser8286b832015-11-02 11:29:32 +00002756 if (isl_set_is_empty(AssumedContext))
2757 return;
2758
2759 updateAccessDimensionality();
Tobias Grosser8cae72f2011-11-08 15:41:08 +00002760 realignParams();
Tobias Grosser18daaca2012-05-22 10:47:27 +00002761 addParameterBounds();
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002762 addUserContext();
Johannes Doerfert883f8c12015-09-15 22:52:53 +00002763 buildBoundaryContext();
2764 simplifyContexts();
Johannes Doerfert120de4b2015-08-20 18:30:08 +00002765 buildAliasChecks(AA);
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002766
2767 hoistInvariantLoads();
Michael Krusecac948e2015-10-02 13:53:07 +00002768 simplifySCoP(false);
Tobias Grosser75805372011-04-29 06:27:02 +00002769}
2770
2771Scop::~Scop() {
2772 isl_set_free(Context);
Tobias Grossere86109f2013-10-29 21:05:49 +00002773 isl_set_free(AssumedContext);
Johannes Doerfert883f8c12015-09-15 22:52:53 +00002774 isl_set_free(BoundaryContext);
Tobias Grosser808cd692015-07-14 09:33:13 +00002775 isl_schedule_free(Schedule);
Tobias Grosser75805372011-04-29 06:27:02 +00002776
Johannes Doerfert96425c22015-08-30 21:13:53 +00002777 for (auto It : DomainMap)
2778 isl_set_free(It.second);
2779
Johannes Doerfertb164c792014-09-18 11:17:17 +00002780 // Free the alias groups
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002781 for (MinMaxVectorPairTy &MinMaxAccessPair : MinMaxAliasGroups) {
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002782 for (MinMaxAccessTy &MMA : MinMaxAccessPair.first) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00002783 isl_pw_multi_aff_free(MMA.first);
2784 isl_pw_multi_aff_free(MMA.second);
2785 }
Johannes Doerfert210b09a2015-07-26 13:14:38 +00002786 for (MinMaxAccessTy &MMA : MinMaxAccessPair.second) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00002787 isl_pw_multi_aff_free(MMA.first);
2788 isl_pw_multi_aff_free(MMA.second);
2789 }
Johannes Doerfertb164c792014-09-18 11:17:17 +00002790 }
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002791
Johannes Doerfert697fdf82015-10-09 17:12:26 +00002792 for (const auto &IAClass : InvariantEquivClasses)
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00002793 isl_set_free(std::get<2>(IAClass));
Tobias Grosser75805372011-04-29 06:27:02 +00002794}
2795
Tobias Grosser99c70dd2015-09-26 08:55:54 +00002796void Scop::updateAccessDimensionality() {
2797 for (auto &Stmt : *this)
2798 for (auto &Access : Stmt)
2799 Access->updateDimensionality();
2800}
2801
Michael Krusecac948e2015-10-02 13:53:07 +00002802void Scop::simplifySCoP(bool RemoveIgnoredStmts) {
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002803 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) {
2804 ScopStmt &Stmt = *StmtIt;
Michael Krusecac948e2015-10-02 13:53:07 +00002805 RegionNode *RN = Stmt.isRegionStmt()
2806 ? Stmt.getRegion()->getNode()
2807 : getRegion().getBBNode(Stmt.getBasicBlock());
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002808
Johannes Doerferteca9e892015-11-03 16:54:49 +00002809 bool RemoveStmt = StmtIt->isEmpty();
2810 if (!RemoveStmt)
2811 RemoveStmt = isl_set_is_empty(DomainMap[getRegionNodeBasicBlock(RN)]);
2812 if (!RemoveStmt)
2813 RemoveStmt = (RemoveIgnoredStmts && isIgnored(RN));
Johannes Doerfertf17a78e2015-10-04 15:00:05 +00002814
Johannes Doerferteca9e892015-11-03 16:54:49 +00002815 // Remove read only statements only after invariant loop hoisting.
2816 if (!RemoveStmt && !RemoveIgnoredStmts) {
2817 bool OnlyRead = true;
2818 for (MemoryAccess *MA : Stmt) {
2819 if (MA->isRead())
2820 continue;
2821
2822 OnlyRead = false;
2823 break;
2824 }
2825
2826 RemoveStmt = OnlyRead;
2827 }
2828
2829 if (RemoveStmt) {
Michael Krusecac948e2015-10-02 13:53:07 +00002830 // Remove the statement because it is unnecessary.
2831 if (Stmt.isRegionStmt())
2832 for (BasicBlock *BB : Stmt.getRegion()->blocks())
2833 StmtMap.erase(BB);
2834 else
2835 StmtMap.erase(Stmt.getBasicBlock());
2836
2837 StmtIt = Stmts.erase(StmtIt);
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002838 continue;
2839 }
2840
Michael Krusecac948e2015-10-02 13:53:07 +00002841 StmtIt++;
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00002842 }
2843}
2844
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00002845const InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) const {
2846 LoadInst *LInst = dyn_cast<LoadInst>(Val);
2847 if (!LInst)
2848 return nullptr;
2849
2850 if (Value *Rep = InvEquivClassVMap.lookup(LInst))
2851 LInst = cast<LoadInst>(Rep);
2852
2853 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
2854 for (auto &IAClass : InvariantEquivClasses)
2855 if (PointerSCEV == std::get<0>(IAClass))
2856 return &IAClass;
2857
2858 return nullptr;
2859}
2860
2861void Scop::addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs) {
2862
2863 // Get the context under which the statement is executed.
2864 isl_set *DomainCtx = isl_set_params(Stmt.getDomain());
2865 DomainCtx = isl_set_remove_redundancies(DomainCtx);
2866 DomainCtx = isl_set_detect_equalities(DomainCtx);
2867 DomainCtx = isl_set_coalesce(DomainCtx);
2868
2869 // Project out all parameters that relate to loads in the statement. Otherwise
2870 // we could have cyclic dependences on the constraints under which the
2871 // hoisted loads are executed and we could not determine an order in which to
2872 // pre-load them. This happens because not only lower bounds are part of the
2873 // domain but also upper bounds.
2874 for (MemoryAccess *MA : InvMAs) {
2875 Instruction *AccInst = MA->getAccessInstruction();
2876 if (SE->isSCEVable(AccInst->getType())) {
Johannes Doerfert44483c52015-11-07 19:45:27 +00002877 SetVector<Value *> Values;
2878 for (const SCEV *Parameter : Parameters) {
2879 Values.clear();
2880 findValues(Parameter, Values);
2881 if (!Values.count(AccInst))
2882 continue;
2883
2884 if (isl_id *ParamId = getIdForParam(Parameter)) {
2885 int Dim = isl_set_find_dim_by_id(DomainCtx, isl_dim_param, ParamId);
2886 DomainCtx = isl_set_eliminate(DomainCtx, isl_dim_param, Dim, 1);
2887 isl_id_free(ParamId);
2888 }
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00002889 }
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00002890 }
2891 }
2892
2893 for (MemoryAccess *MA : InvMAs) {
2894 // Check for another invariant access that accesses the same location as
2895 // MA and if found consolidate them. Otherwise create a new equivalence
2896 // class at the end of InvariantEquivClasses.
2897 LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
2898 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
2899
2900 bool Consolidated = false;
2901 for (auto &IAClass : InvariantEquivClasses) {
2902 if (PointerSCEV != std::get<0>(IAClass))
2903 continue;
2904
2905 Consolidated = true;
2906
2907 // Add MA to the list of accesses that are in this class.
2908 auto &MAs = std::get<1>(IAClass);
2909 MAs.push_front(MA);
2910
2911 // Unify the execution context of the class and this statement.
2912 isl_set *&IAClassDomainCtx = std::get<2>(IAClass);
Johannes Doerfertfc4bfc42015-11-11 04:30:07 +00002913 if (IAClassDomainCtx)
2914 IAClassDomainCtx = isl_set_coalesce(
2915 isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx)));
2916 else
2917 IAClassDomainCtx = isl_set_copy(DomainCtx);
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00002918 break;
2919 }
2920
2921 if (Consolidated)
2922 continue;
2923
2924 // If we did not consolidate MA, thus did not find an equivalence class
2925 // for it, we create a new one.
2926 InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA},
2927 isl_set_copy(DomainCtx));
2928 }
2929
2930 isl_set_free(DomainCtx);
2931}
2932
Tobias Grosser29f38ab2015-12-13 21:00:40 +00002933bool Scop::isHoistableAccess(MemoryAccess *Access,
2934 __isl_keep isl_union_map *Writes) {
2935 // TODO: Loads that are not loop carried, hence are in a statement with
2936 // zero iterators, are by construction invariant, though we
2937 // currently "hoist" them anyway. This is necessary because we allow
2938 // them to be treated as parameters (e.g., in conditions) and our code
2939 // generation would otherwise use the old value.
2940
2941 auto &Stmt = *Access->getStatement();
2942 BasicBlock *BB =
2943 Stmt.isBlockStmt() ? Stmt.getBasicBlock() : Stmt.getRegion()->getEntry();
2944
2945 if (Access->isScalarKind() || Access->isWrite() || !Access->isAffine())
2946 return false;
2947
2948 // Skip accesses that have an invariant base pointer which is defined but
2949 // not loaded inside the SCoP. This can happened e.g., if a readnone call
2950 // returns a pointer that is used as a base address. However, as we want
2951 // to hoist indirect pointers, we allow the base pointer to be defined in
2952 // the region if it is also a memory access. Each ScopArrayInfo object
2953 // that has a base pointer origin has a base pointer that is loaded and
2954 // that it is invariant, thus it will be hoisted too. However, if there is
2955 // no base pointer origin we check that the base pointer is defined
2956 // outside the region.
2957 const ScopArrayInfo *SAI = Access->getScopArrayInfo();
2958 while (auto *BasePtrOriginSAI = SAI->getBasePtrOriginSAI())
2959 SAI = BasePtrOriginSAI;
2960
2961 if (auto *BasePtrInst = dyn_cast<Instruction>(SAI->getBasePtr()))
2962 if (R.contains(BasePtrInst))
2963 return false;
2964
2965 // Skip accesses in non-affine subregions as they might not be executed
2966 // under the same condition as the entry of the non-affine subregion.
2967 if (BB != Access->getAccessInstruction()->getParent())
2968 return false;
2969
2970 isl_map *AccessRelation = Access->getAccessRelation();
2971
2972 // Skip accesses that have an empty access relation. These can be caused
2973 // by multiple offsets with a type cast in-between that cause the overall
2974 // byte offset to be not divisible by the new types sizes.
2975 if (isl_map_is_empty(AccessRelation)) {
2976 isl_map_free(AccessRelation);
2977 return false;
2978 }
2979
2980 if (isl_map_involves_dims(AccessRelation, isl_dim_in, 0,
2981 Stmt.getNumIterators())) {
2982 isl_map_free(AccessRelation);
2983 return false;
2984 }
2985
2986 AccessRelation = isl_map_intersect_domain(AccessRelation, Stmt.getDomain());
2987 isl_set *AccessRange = isl_map_range(AccessRelation);
2988
2989 isl_union_map *Written = isl_union_map_intersect_range(
2990 isl_union_map_copy(Writes), isl_union_set_from_set(AccessRange));
2991 bool IsWritten = !isl_union_map_is_empty(Written);
2992 isl_union_map_free(Written);
2993
2994 if (IsWritten)
2995 return false;
2996
2997 return true;
2998}
2999
3000void Scop::verifyInvariantLoads() {
3001 auto &RIL = *SD.getRequiredInvariantLoads(&getRegion());
3002 for (LoadInst *LI : RIL) {
3003 assert(LI && getRegion().contains(LI));
3004 ScopStmt *Stmt = getStmtForBasicBlock(LI->getParent());
Tobias Grosser949e8c62015-12-21 07:10:39 +00003005 if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) {
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003006 invalidate(INVARIANTLOAD, LI->getDebugLoc());
3007 return;
3008 }
3009 }
3010}
3011
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003012void Scop::hoistInvariantLoads() {
3013 isl_union_map *Writes = getWrites();
3014 for (ScopStmt &Stmt : *this) {
3015
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003016 MemoryAccessList InvariantAccesses;
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003017
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003018 for (MemoryAccess *Access : Stmt)
3019 if (isHoistableAccess(Access, Writes))
3020 InvariantAccesses.push_front(Access);
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003021
3022 // We inserted invariant accesses always in the front but need them to be
3023 // sorted in a "natural order". The statements are already sorted in reverse
3024 // post order and that suffices for the accesses too. The reason we require
3025 // an order in the first place is the dependences between invariant loads
3026 // that can be caused by indirect loads.
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003027 InvariantAccesses.reverse();
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003028
3029 // Transfer the memory access from the statement to the SCoP.
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003030 Stmt.removeMemoryAccesses(InvariantAccesses);
3031 addInvariantLoads(Stmt, InvariantAccesses);
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003032 }
3033 isl_union_map_free(Writes);
3034
Tobias Grosser29f38ab2015-12-13 21:00:40 +00003035 verifyInvariantLoads();
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003036}
3037
Johannes Doerfert80ef1102014-11-07 08:31:31 +00003038const ScopArrayInfo *
Tobias Grossercc779502016-02-02 13:22:54 +00003039Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
Tobias Grosser6abc75a2015-11-10 17:31:31 +00003040 ArrayRef<const SCEV *> Sizes,
Tobias Grossera535dff2015-12-13 19:59:01 +00003041 ScopArrayInfo::MemoryKind Kind) {
Tobias Grosser6abc75a2015-11-10 17:31:31 +00003042 auto &SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)];
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003043 if (!SAI) {
Johannes Doerfert55b3d8b2015-11-12 20:15:08 +00003044 auto &DL = getRegion().getEntry()->getModule()->getDataLayout();
Tobias Grossercc779502016-02-02 13:22:54 +00003045 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind,
Johannes Doerfert55b3d8b2015-11-12 20:15:08 +00003046 DL, this));
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003047 } else {
Tobias Grosser8286b832015-11-02 11:29:32 +00003048 // In case of mismatching array sizes, we bail out by setting the run-time
3049 // context to false.
Tobias Grosserd840fc72016-02-04 13:18:42 +00003050 if (!SAI->updateSizes(Sizes, ElementType))
Tobias Grosser8d4f6262015-12-12 09:52:26 +00003051 invalidate(DELINEARIZATION, DebugLoc());
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003052 }
Tobias Grosserab671442015-05-23 05:58:27 +00003053 return SAI.get();
Johannes Doerfert1a28a892014-10-05 11:32:18 +00003054}
3055
Tobias Grosser6abc75a2015-11-10 17:31:31 +00003056const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr,
Tobias Grossera535dff2015-12-13 19:59:01 +00003057 ScopArrayInfo::MemoryKind Kind) {
Tobias Grosser6abc75a2015-11-10 17:31:31 +00003058 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
Johannes Doerfert1a28a892014-10-05 11:32:18 +00003059 assert(SAI && "No ScopArrayInfo available for this base pointer");
3060 return SAI;
3061}
3062
Tobias Grosser74394f02013-01-14 22:40:23 +00003063std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003064std::string Scop::getAssumedContextStr() const {
3065 return stringFromIslObj(AssumedContext);
3066}
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003067std::string Scop::getBoundaryContextStr() const {
3068 return stringFromIslObj(BoundaryContext);
3069}
Tobias Grosser75805372011-04-29 06:27:02 +00003070
3071std::string Scop::getNameStr() const {
3072 std::string ExitName, EntryName;
3073 raw_string_ostream ExitStr(ExitName);
3074 raw_string_ostream EntryStr(EntryName);
3075
Tobias Grosserf240b482014-01-09 10:42:15 +00003076 R.getEntry()->printAsOperand(EntryStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00003077 EntryStr.str();
3078
3079 if (R.getExit()) {
Tobias Grosserf240b482014-01-09 10:42:15 +00003080 R.getExit()->printAsOperand(ExitStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00003081 ExitStr.str();
3082 } else
3083 ExitName = "FunctionExit";
3084
3085 return EntryName + "---" + ExitName;
3086}
3087
Tobias Grosser74394f02013-01-14 22:40:23 +00003088__isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); }
Tobias Grosser37487052011-10-06 00:03:42 +00003089__isl_give isl_space *Scop::getParamSpace() const {
Tobias Grossereeb9f3c2015-05-26 21:37:31 +00003090 return isl_set_get_space(Context);
Tobias Grosser37487052011-10-06 00:03:42 +00003091}
3092
Tobias Grossere86109f2013-10-29 21:05:49 +00003093__isl_give isl_set *Scop::getAssumedContext() const {
3094 return isl_set_copy(AssumedContext);
3095}
3096
Johannes Doerfert43788c52015-08-20 05:58:56 +00003097__isl_give isl_set *Scop::getRuntimeCheckContext() const {
3098 isl_set *RuntimeCheckContext = getAssumedContext();
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003099 RuntimeCheckContext =
3100 isl_set_intersect(RuntimeCheckContext, getBoundaryContext());
3101 RuntimeCheckContext = simplifyAssumptionContext(RuntimeCheckContext, *this);
Johannes Doerfert43788c52015-08-20 05:58:56 +00003102 return RuntimeCheckContext;
3103}
3104
Johannes Doerfert5d5b3062015-08-20 18:06:30 +00003105bool Scop::hasFeasibleRuntimeContext() const {
Johannes Doerfert43788c52015-08-20 05:58:56 +00003106 isl_set *RuntimeCheckContext = getRuntimeCheckContext();
Johannes Doerfert5d5b3062015-08-20 18:06:30 +00003107 RuntimeCheckContext = addNonEmptyDomainConstraints(RuntimeCheckContext);
Johannes Doerfert43788c52015-08-20 05:58:56 +00003108 bool IsFeasible = !isl_set_is_empty(RuntimeCheckContext);
3109 isl_set_free(RuntimeCheckContext);
3110 return IsFeasible;
3111}
3112
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003113static std::string toString(AssumptionKind Kind) {
3114 switch (Kind) {
3115 case ALIASING:
3116 return "No-aliasing";
3117 case INBOUNDS:
3118 return "Inbounds";
3119 case WRAPPING:
3120 return "No-overflows";
Johannes Doerferta4b77c02015-11-12 20:15:32 +00003121 case ALIGNMENT:
3122 return "Alignment";
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003123 case ERRORBLOCK:
3124 return "No-error";
3125 case INFINITELOOP:
3126 return "Finite loop";
3127 case INVARIANTLOAD:
3128 return "Invariant load";
3129 case DELINEARIZATION:
3130 return "Delinearization";
Tobias Grosser75dc40c2015-12-20 13:31:48 +00003131 case ERROR_DOMAINCONJUNCTS:
3132 return "Low number of domain conjuncts";
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003133 }
3134 llvm_unreachable("Unknown AssumptionKind!");
3135}
3136
3137void Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set,
3138 DebugLoc Loc) {
3139 if (isl_set_is_subset(Context, Set))
3140 return;
3141
3142 if (isl_set_is_subset(AssumedContext, Set))
3143 return;
3144
3145 auto &F = *getRegion().getEntry()->getParent();
3146 std::string Msg = toString(Kind) + " assumption:\t" + stringFromIslObj(Set);
3147 emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg);
3148}
3149
3150void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set,
3151 DebugLoc Loc) {
3152 trackAssumption(Kind, Set, Loc);
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003153 AssumedContext = isl_set_intersect(AssumedContext, Set);
Tobias Grosser20a4c0c2015-11-11 16:22:36 +00003154
Johannes Doerfert9d7899e2015-11-11 20:01:31 +00003155 int NSets = isl_set_n_basic_set(AssumedContext);
Tobias Grosser20a4c0c2015-11-11 16:22:36 +00003156 if (NSets >= MaxDisjunctsAssumed) {
3157 isl_space *Space = isl_set_get_space(AssumedContext);
3158 isl_set_free(AssumedContext);
Tobias Grossere19fca42015-11-11 20:21:39 +00003159 AssumedContext = isl_set_empty(Space);
Tobias Grosser20a4c0c2015-11-11 16:22:36 +00003160 }
3161
Tobias Grosser7b50bee2014-11-25 10:51:12 +00003162 AssumedContext = isl_set_coalesce(AssumedContext);
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003163}
3164
Tobias Grosser8d4f6262015-12-12 09:52:26 +00003165void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc) {
3166 addAssumption(Kind, isl_set_empty(getParamSpace()), Loc);
3167}
3168
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003169__isl_give isl_set *Scop::getBoundaryContext() const {
3170 return isl_set_copy(BoundaryContext);
3171}
3172
Tobias Grosser75805372011-04-29 06:27:02 +00003173void Scop::printContext(raw_ostream &OS) const {
3174 OS << "Context:\n";
3175
3176 if (!Context) {
3177 OS.indent(4) << "n/a\n\n";
3178 return;
3179 }
3180
3181 OS.indent(4) << getContextStr() << "\n";
Tobias Grosser60b54f12011-11-08 15:41:28 +00003182
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003183 OS.indent(4) << "Assumed Context:\n";
3184 if (!AssumedContext) {
3185 OS.indent(4) << "n/a\n\n";
3186 return;
3187 }
3188
3189 OS.indent(4) << getAssumedContextStr() << "\n";
3190
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003191 OS.indent(4) << "Boundary Context:\n";
3192 if (!BoundaryContext) {
3193 OS.indent(4) << "n/a\n\n";
3194 return;
3195 }
3196
3197 OS.indent(4) << getBoundaryContextStr() << "\n";
3198
Tobias Grosser083d3d32014-06-28 08:59:45 +00003199 for (const SCEV *Parameter : Parameters) {
Tobias Grosser60b54f12011-11-08 15:41:28 +00003200 int Dim = ParameterIds.find(Parameter)->second;
Tobias Grosser60b54f12011-11-08 15:41:28 +00003201 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n";
3202 }
Tobias Grosser75805372011-04-29 06:27:02 +00003203}
3204
Johannes Doerfertb164c792014-09-18 11:17:17 +00003205void Scop::printAliasAssumptions(raw_ostream &OS) const {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003206 int noOfGroups = 0;
3207 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) {
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003208 if (Pair.second.size() == 0)
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003209 noOfGroups += 1;
3210 else
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003211 noOfGroups += Pair.second.size();
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003212 }
3213
Tobias Grosserbb853c22015-07-25 12:31:03 +00003214 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n";
Johannes Doerfertb164c792014-09-18 11:17:17 +00003215 if (MinMaxAliasGroups.empty()) {
3216 OS.indent(8) << "n/a\n";
3217 return;
3218 }
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003219
Tobias Grosserbb853c22015-07-25 12:31:03 +00003220 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003221
3222 // If the group has no read only accesses print the write accesses.
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003223 if (Pair.second.empty()) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003224 OS.indent(8) << "[[";
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003225 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003226 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3227 << ">";
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003228 }
3229 OS << " ]]\n";
3230 }
3231
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003232 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003233 OS.indent(8) << "[[";
Tobias Grosserbb853c22015-07-25 12:31:03 +00003234 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">";
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003235 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003236 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3237 << ">";
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003238 }
3239 OS << " ]]\n";
3240 }
Johannes Doerfertb164c792014-09-18 11:17:17 +00003241 }
3242}
3243
Tobias Grosser75805372011-04-29 06:27:02 +00003244void Scop::printStatements(raw_ostream &OS) const {
3245 OS << "Statements {\n";
3246
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003247 for (const ScopStmt &Stmt : *this)
3248 OS.indent(4) << Stmt;
Tobias Grosser75805372011-04-29 06:27:02 +00003249
3250 OS.indent(4) << "}\n";
3251}
3252
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003253void Scop::printArrayInfo(raw_ostream &OS) const {
3254 OS << "Arrays {\n";
3255
Tobias Grosserab671442015-05-23 05:58:27 +00003256 for (auto &Array : arrays())
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003257 Array.second->print(OS);
3258
3259 OS.indent(4) << "}\n";
Tobias Grosserd46fd5e2015-08-12 15:27:16 +00003260
3261 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n";
3262
3263 for (auto &Array : arrays())
3264 Array.second->print(OS, /* SizeAsPwAff */ true);
3265
3266 OS.indent(4) << "}\n";
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003267}
3268
Tobias Grosser75805372011-04-29 06:27:02 +00003269void Scop::print(raw_ostream &OS) const {
Tobias Grosser4eb7ddb2014-03-18 18:51:11 +00003270 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName()
3271 << "\n";
Tobias Grosser483fdd42014-03-18 18:05:38 +00003272 OS.indent(4) << "Region: " << getNameStr() << "\n";
David Peixottodc0a11c2015-01-13 18:31:55 +00003273 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n";
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003274 OS.indent(4) << "Invariant Accesses: {\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003275 for (const auto &IAClass : InvariantEquivClasses) {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003276 const auto &MAs = std::get<1>(IAClass);
3277 if (MAs.empty()) {
3278 OS.indent(12) << "Class Pointer: " << *std::get<0>(IAClass) << "\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003279 } else {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003280 MAs.front()->print(OS);
3281 OS.indent(12) << "Execution Context: " << std::get<2>(IAClass) << "\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003282 }
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003283 }
3284 OS.indent(4) << "}\n";
Tobias Grosser75805372011-04-29 06:27:02 +00003285 printContext(OS.indent(4));
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003286 printArrayInfo(OS.indent(4));
Johannes Doerfertb164c792014-09-18 11:17:17 +00003287 printAliasAssumptions(OS);
Tobias Grosser75805372011-04-29 06:27:02 +00003288 printStatements(OS.indent(4));
3289}
3290
3291void Scop::dump() const { print(dbgs()); }
3292
Tobias Grosser9a38ab82011-11-08 15:41:03 +00003293isl_ctx *Scop::getIslCtx() const { return IslCtx; }
Tobias Grosser75805372011-04-29 06:27:02 +00003294
Johannes Doerfertcef616f2015-09-15 22:49:04 +00003295__isl_give isl_pw_aff *Scop::getPwAff(const SCEV *E, BasicBlock *BB) {
3296 return Affinator.getPwAff(E, BB);
Johannes Doerfert574182d2015-08-12 10:19:50 +00003297}
3298
Tobias Grosser808cd692015-07-14 09:33:13 +00003299__isl_give isl_union_set *Scop::getDomains() const {
Tobias Grosserbc4ef902014-06-28 08:59:38 +00003300 isl_union_set *Domain = isl_union_set_empty(getParamSpace());
Tobias Grosser5f9a7622012-02-14 14:02:40 +00003301
Tobias Grosser808cd692015-07-14 09:33:13 +00003302 for (const ScopStmt &Stmt : *this)
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003303 Domain = isl_union_set_add_set(Domain, Stmt.getDomain());
Tobias Grosser5f9a7622012-02-14 14:02:40 +00003304
3305 return Domain;
3306}
3307
Tobias Grossere5a35142015-11-12 14:07:09 +00003308__isl_give isl_union_map *
3309Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) {
3310 isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003311
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003312 for (ScopStmt &Stmt : *this) {
3313 for (MemoryAccess *MA : Stmt) {
Tobias Grossere5a35142015-11-12 14:07:09 +00003314 if (!Predicate(*MA))
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003315 continue;
3316
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003317 isl_set *Domain = Stmt.getDomain();
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003318 isl_map *AccessDomain = MA->getAccessRelation();
3319 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
Tobias Grossere5a35142015-11-12 14:07:09 +00003320 Accesses = isl_union_map_add_map(Accesses, AccessDomain);
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003321 }
3322 }
Tobias Grossere5a35142015-11-12 14:07:09 +00003323 return isl_union_map_coalesce(Accesses);
3324}
3325
3326__isl_give isl_union_map *Scop::getMustWrites() {
3327 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); });
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003328}
3329
3330__isl_give isl_union_map *Scop::getMayWrites() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003331 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); });
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003332}
3333
Tobias Grosser37eb4222014-02-20 21:43:54 +00003334__isl_give isl_union_map *Scop::getWrites() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003335 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); });
Tobias Grosser37eb4222014-02-20 21:43:54 +00003336}
3337
3338__isl_give isl_union_map *Scop::getReads() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003339 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); });
Tobias Grosser37eb4222014-02-20 21:43:54 +00003340}
3341
Tobias Grosser2ac23382015-11-12 14:07:13 +00003342__isl_give isl_union_map *Scop::getAccesses() {
3343 return getAccessesOfType([](MemoryAccess &MA) { return true; });
3344}
3345
Tobias Grosser808cd692015-07-14 09:33:13 +00003346__isl_give isl_union_map *Scop::getSchedule() const {
3347 auto Tree = getScheduleTree();
3348 auto S = isl_schedule_get_map(Tree);
3349 isl_schedule_free(Tree);
3350 return S;
3351}
Tobias Grosser37eb4222014-02-20 21:43:54 +00003352
Tobias Grosser808cd692015-07-14 09:33:13 +00003353__isl_give isl_schedule *Scop::getScheduleTree() const {
3354 return isl_schedule_intersect_domain(isl_schedule_copy(Schedule),
3355 getDomains());
3356}
Tobias Grosserbc4ef902014-06-28 08:59:38 +00003357
Tobias Grosser808cd692015-07-14 09:33:13 +00003358void Scop::setSchedule(__isl_take isl_union_map *NewSchedule) {
3359 auto *S = isl_schedule_from_domain(getDomains());
3360 S = isl_schedule_insert_partial_schedule(
3361 S, isl_multi_union_pw_aff_from_union_map(NewSchedule));
3362 isl_schedule_free(Schedule);
3363 Schedule = S;
3364}
3365
3366void Scop::setScheduleTree(__isl_take isl_schedule *NewSchedule) {
3367 isl_schedule_free(Schedule);
3368 Schedule = NewSchedule;
Tobias Grosser37eb4222014-02-20 21:43:54 +00003369}
3370
3371bool Scop::restrictDomains(__isl_take isl_union_set *Domain) {
3372 bool Changed = false;
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003373 for (ScopStmt &Stmt : *this) {
3374 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt.getDomain());
Tobias Grosser37eb4222014-02-20 21:43:54 +00003375 isl_union_set *NewStmtDomain = isl_union_set_intersect(
3376 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain));
3377
3378 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) {
3379 isl_union_set_free(StmtDomain);
3380 isl_union_set_free(NewStmtDomain);
3381 continue;
3382 }
3383
3384 Changed = true;
3385
3386 isl_union_set_free(StmtDomain);
3387 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain);
3388
3389 if (isl_union_set_is_empty(NewStmtDomain)) {
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003390 Stmt.restrictDomain(isl_set_empty(Stmt.getDomainSpace()));
Tobias Grosser37eb4222014-02-20 21:43:54 +00003391 isl_union_set_free(NewStmtDomain);
3392 } else
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003393 Stmt.restrictDomain(isl_set_from_union_set(NewStmtDomain));
Tobias Grosser37eb4222014-02-20 21:43:54 +00003394 }
3395 isl_union_set_free(Domain);
3396 return Changed;
3397}
3398
Tobias Grosser75805372011-04-29 06:27:02 +00003399ScalarEvolution *Scop::getSE() const { return SE; }
3400
Johannes Doerfertf5673802015-10-01 23:48:18 +00003401bool Scop::isIgnored(RegionNode *RN) {
3402 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Michael Krusea902ba62015-12-13 19:21:45 +00003403 ScopStmt *Stmt = getStmtForRegionNode(RN);
3404
3405 // If there is no stmt, then it already has been removed.
3406 if (!Stmt)
3407 return true;
Tobias Grosser75805372011-04-29 06:27:02 +00003408
Johannes Doerfertf5673802015-10-01 23:48:18 +00003409 // Check if there are accesses contained.
Michael Krusea902ba62015-12-13 19:21:45 +00003410 if (Stmt->isEmpty())
Johannes Doerfertf5673802015-10-01 23:48:18 +00003411 return true;
3412
3413 // Check for reachability via non-error blocks.
3414 if (!DomainMap.count(BB))
3415 return true;
3416
3417 // Check if error blocks are contained.
Johannes Doerfert08d90a32015-10-07 20:32:43 +00003418 if (containsErrorBlock(RN, getRegion(), LI, DT))
Johannes Doerfertf5673802015-10-01 23:48:18 +00003419 return true;
3420
3421 return false;
Tobias Grosser75805372011-04-29 06:27:02 +00003422}
3423
Tobias Grosser808cd692015-07-14 09:33:13 +00003424struct MapToDimensionDataTy {
3425 int N;
3426 isl_union_pw_multi_aff *Res;
3427};
Johannes Doerfertff9d1982015-02-24 12:00:50 +00003428
Tobias Grosser808cd692015-07-14 09:33:13 +00003429// @brief Create a function that maps the elements of 'Set' to its N-th
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003430// dimension and add it to User->Res.
Tobias Grosser808cd692015-07-14 09:33:13 +00003431//
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003432// @param Set The input set.
3433// @param User->N The dimension to map to.
3434// @param User->Res The isl_union_pw_multi_aff to which to add the result.
Tobias Grosser808cd692015-07-14 09:33:13 +00003435//
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003436// @returns isl_stat_ok if no error occured, othewise isl_stat_error.
Tobias Grosser808cd692015-07-14 09:33:13 +00003437static isl_stat mapToDimension_AddSet(__isl_take isl_set *Set, void *User) {
3438 struct MapToDimensionDataTy *Data = (struct MapToDimensionDataTy *)User;
3439 int Dim;
3440 isl_space *Space;
3441 isl_pw_multi_aff *PMA;
3442
3443 Dim = isl_set_dim(Set, isl_dim_set);
3444 Space = isl_set_get_space(Set);
3445 PMA = isl_pw_multi_aff_project_out_map(Space, isl_dim_set, Data->N,
3446 Dim - Data->N);
3447 if (Data->N > 1)
3448 PMA = isl_pw_multi_aff_drop_dims(PMA, isl_dim_out, 0, Data->N - 1);
3449 Data->Res = isl_union_pw_multi_aff_add_pw_multi_aff(Data->Res, PMA);
3450
3451 isl_set_free(Set);
3452
3453 return isl_stat_ok;
Johannes Doerfertff9d1982015-02-24 12:00:50 +00003454}
3455
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003456// @brief Create an isl_multi_union_aff that defines an identity mapping
3457// from the elements of USet to their N-th dimension.
Tobias Grosser808cd692015-07-14 09:33:13 +00003458//
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003459// # Example:
3460//
3461// Domain: { A[i,j]; B[i,j,k] }
3462// N: 1
3463//
3464// Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] }
3465//
3466// @param USet A union set describing the elements for which to generate a
3467// mapping.
Tobias Grosser808cd692015-07-14 09:33:13 +00003468// @param N The dimension to map to.
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003469// @returns A mapping from USet to its N-th dimension.
Tobias Grosser808cd692015-07-14 09:33:13 +00003470static __isl_give isl_multi_union_pw_aff *
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003471mapToDimension(__isl_take isl_union_set *USet, int N) {
3472 assert(N >= 0);
Tobias Grosserc900633d2015-12-21 23:01:53 +00003473 assert(USet);
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003474 assert(!isl_union_set_is_empty(USet));
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00003475
Tobias Grosser808cd692015-07-14 09:33:13 +00003476 struct MapToDimensionDataTy Data;
Tobias Grosser808cd692015-07-14 09:33:13 +00003477
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003478 auto *Space = isl_union_set_get_space(USet);
3479 auto *PwAff = isl_union_pw_multi_aff_empty(Space);
Tobias Grosser808cd692015-07-14 09:33:13 +00003480
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003481 Data = {N, PwAff};
3482
3483 auto Res = isl_union_set_foreach_set(USet, &mapToDimension_AddSet, &Data);
3484
Sumanth Gundapaneni4b1472f2016-01-20 15:41:30 +00003485 (void)Res;
3486
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003487 assert(Res == isl_stat_ok);
3488
3489 isl_union_set_free(USet);
Tobias Grosser808cd692015-07-14 09:33:13 +00003490 return isl_multi_union_pw_aff_from_union_pw_multi_aff(Data.Res);
3491}
3492
Tobias Grosser316b5b22015-11-11 19:28:14 +00003493void Scop::addScopStmt(BasicBlock *BB, Region *R) {
Tobias Grosser808cd692015-07-14 09:33:13 +00003494 if (BB) {
Michael Kruse9d080092015-09-11 21:41:48 +00003495 Stmts.emplace_back(*this, *BB);
Tobias Grosser316b5b22015-11-11 19:28:14 +00003496 auto Stmt = &Stmts.back();
Tobias Grosser808cd692015-07-14 09:33:13 +00003497 StmtMap[BB] = Stmt;
3498 } else {
3499 assert(R && "Either basic block or a region expected.");
Michael Kruse9d080092015-09-11 21:41:48 +00003500 Stmts.emplace_back(*this, *R);
Tobias Grosser316b5b22015-11-11 19:28:14 +00003501 auto Stmt = &Stmts.back();
Tobias Grosser808cd692015-07-14 09:33:13 +00003502 for (BasicBlock *BB : R->blocks())
3503 StmtMap[BB] = Stmt;
3504 }
Tobias Grosser808cd692015-07-14 09:33:13 +00003505}
3506
Johannes Doerfertf9711ef2016-01-06 12:59:23 +00003507void Scop::buildSchedule() {
Johannes Doerfertf9711ef2016-01-06 12:59:23 +00003508 Loop *L = getLoopSurroundingRegion(getRegion(), LI);
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003509 LoopStackTy LoopStack({LoopStackElementTy(L, nullptr, 0)});
3510 buildSchedule(getRegion().getNode(), LoopStack);
3511 assert(LoopStack.size() == 1 && LoopStack.back().L == L);
3512 Schedule = LoopStack[0].Schedule;
Johannes Doerfertf9711ef2016-01-06 12:59:23 +00003513}
3514
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003515/// To generate a schedule for the elements in a Region we traverse the Region
3516/// in reverse-post-order and add the contained RegionNodes in traversal order
3517/// to the schedule of the loop that is currently at the top of the LoopStack.
3518/// For loop-free codes, this results in a correct sequential ordering.
3519///
3520/// Example:
3521/// bb1(0)
3522/// / \.
3523/// bb2(1) bb3(2)
3524/// \ / \.
3525/// bb4(3) bb5(4)
3526/// \ /
3527/// bb6(5)
3528///
3529/// Including loops requires additional processing. Whenever a loop header is
3530/// encountered, the corresponding loop is added to the @p LoopStack. Starting
3531/// from an empty schedule, we first process all RegionNodes that are within
3532/// this loop and complete the sequential schedule at this loop-level before
3533/// processing about any other nodes. To implement this
3534/// loop-nodes-first-processing, the reverse post-order traversal is
3535/// insufficient. Hence, we additionally check if the traversal yields
3536/// sub-regions or blocks that are outside the last loop on the @p LoopStack.
3537/// These region-nodes are then queue and only traverse after the all nodes
3538/// within the current loop have been processed.
3539void Scop::buildSchedule(Region *R, LoopStackTy &LoopStack) {
3540 Loop *OuterScopLoop = getLoopSurroundingRegion(getRegion(), LI);
3541
3542 ReversePostOrderTraversal<Region *> RTraversal(R);
3543 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end());
3544 std::deque<RegionNode *> DelayList;
3545 bool LastRNWaiting = false;
3546
3547 // Iterate over the region @p R in reverse post-order but queue
3548 // sub-regions/blocks iff they are not part of the last encountered but not
3549 // completely traversed loop. The variable LastRNWaiting is a flag to indicate
3550 // that we queued the last sub-region/block from the reverse post-order
3551 // iterator. If it is set we have to explore the next sub-region/block from
3552 // the iterator (if any) to guarantee progress. If it is not set we first try
3553 // the next queued sub-region/blocks.
3554 while (!WorkList.empty() || !DelayList.empty()) {
3555 RegionNode *RN;
3556
3557 if ((LastRNWaiting && !WorkList.empty()) || DelayList.size() == 0) {
3558 RN = WorkList.front();
3559 WorkList.pop_front();
3560 LastRNWaiting = false;
3561 } else {
3562 RN = DelayList.front();
3563 DelayList.pop_front();
3564 }
3565
3566 Loop *L = getRegionNodeLoop(RN, LI);
3567 if (!getRegion().contains(L))
3568 L = OuterScopLoop;
3569
3570 Loop *LastLoop = LoopStack.back().L;
3571 if (LastLoop != L) {
3572 if (!LastLoop->contains(L)) {
3573 LastRNWaiting = true;
3574 DelayList.push_back(RN);
3575 continue;
3576 }
3577 LoopStack.push_back({L, nullptr, 0});
3578 }
3579 buildSchedule(RN, LoopStack);
3580 }
3581
3582 return;
3583}
3584
3585void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack) {
Michael Kruse046dde42015-08-10 13:01:57 +00003586
Tobias Grosser8362c262016-01-06 15:30:06 +00003587 if (RN->isSubRegion()) {
3588 auto *LocalRegion = RN->getNodeAs<Region>();
3589 if (!SD.isNonAffineSubRegion(LocalRegion, &getRegion())) {
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003590 buildSchedule(LocalRegion, LoopStack);
Tobias Grosser8362c262016-01-06 15:30:06 +00003591 return;
3592 }
3593 }
Michael Kruse046dde42015-08-10 13:01:57 +00003594
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003595 auto &LoopData = LoopStack.back();
3596 LoopData.NumBlocksProcessed += getNumBlocksInRegionNode(RN);
Tobias Grosser8362c262016-01-06 15:30:06 +00003597
Tobias Grosserc9abde82016-01-23 20:23:06 +00003598 if (auto *Stmt = getStmtForRegionNode(RN)) {
Tobias Grosser8362c262016-01-06 15:30:06 +00003599 auto *UDomain = isl_union_set_from_set(Stmt->getDomain());
3600 auto *StmtSchedule = isl_schedule_from_domain(UDomain);
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003601 LoopData.Schedule = combineInSequence(LoopData.Schedule, StmtSchedule);
Tobias Grosser8362c262016-01-06 15:30:06 +00003602 }
3603
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003604 // Check if we just processed the last node in this loop. If we did, finalize
3605 // the loop by:
3606 //
3607 // - adding new schedule dimensions
3608 // - folding the resulting schedule into the parent loop schedule
3609 // - dropping the loop schedule from the LoopStack.
3610 //
3611 // Then continue to check surrounding loops, which might also have been
3612 // completed by this node.
3613 while (LoopData.L &&
3614 LoopData.NumBlocksProcessed == LoopData.L->getNumBlocks()) {
3615 auto Schedule = LoopData.Schedule;
3616 auto NumBlocksProcessed = LoopData.NumBlocksProcessed;
Tobias Grosser8362c262016-01-06 15:30:06 +00003617
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003618 LoopStack.pop_back();
3619 auto &NextLoopData = LoopStack.back();
Tobias Grosser8362c262016-01-06 15:30:06 +00003620
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003621 if (Schedule) {
3622 auto *Domain = isl_schedule_get_domain(Schedule);
3623 auto *MUPA = mapToDimension(Domain, LoopStack.size());
3624 Schedule = isl_schedule_insert_partial_schedule(Schedule, MUPA);
3625 NextLoopData.Schedule =
3626 combineInSequence(NextLoopData.Schedule, Schedule);
Tobias Grosser75805372011-04-29 06:27:02 +00003627 }
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00003628
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003629 NextLoopData.NumBlocksProcessed += NumBlocksProcessed;
3630 LoopData = NextLoopData;
Tobias Grosser808cd692015-07-14 09:33:13 +00003631 }
Tobias Grosser75805372011-04-29 06:27:02 +00003632}
3633
Johannes Doerfert7c494212014-10-31 23:13:39 +00003634ScopStmt *Scop::getStmtForBasicBlock(BasicBlock *BB) const {
Tobias Grosser57411e32015-05-27 06:51:34 +00003635 auto StmtMapIt = StmtMap.find(BB);
Johannes Doerfert7c494212014-10-31 23:13:39 +00003636 if (StmtMapIt == StmtMap.end())
3637 return nullptr;
3638 return StmtMapIt->second;
3639}
3640
Michael Krusea902ba62015-12-13 19:21:45 +00003641ScopStmt *Scop::getStmtForRegionNode(RegionNode *RN) const {
3642 return getStmtForBasicBlock(getRegionNodeBasicBlock(RN));
3643}
3644
Johannes Doerfert96425c22015-08-30 21:13:53 +00003645int Scop::getRelativeLoopDepth(const Loop *L) const {
3646 Loop *OuterLoop =
3647 L ? R.outermostLoopInRegion(const_cast<Loop *>(L)) : nullptr;
3648 if (!OuterLoop)
3649 return -1;
Johannes Doerfertd020b772015-08-27 06:53:52 +00003650 return L->getLoopDepth() - OuterLoop->getLoopDepth();
3651}
3652
Michael Krused868b5d2015-09-10 15:25:24 +00003653void ScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
Michael Krused868b5d2015-09-10 15:25:24 +00003654 Region *NonAffineSubRegion, bool IsExitBlock) {
Michael Kruse7bf39442015-09-10 12:46:52 +00003655
3656 // PHI nodes that are in the exit block of the region, hence if IsExitBlock is
3657 // true, are not modeled as ordinary PHI nodes as they are not part of the
3658 // region. However, we model the operands in the predecessor blocks that are
3659 // part of the region as regular scalar accesses.
3660
3661 // If we can synthesize a PHI we can skip it, however only if it is in
3662 // the region. If it is not it can only be in the exit block of the region.
3663 // In this case we model the operands but not the PHI itself.
3664 if (!IsExitBlock && canSynthesize(PHI, LI, SE, &R))
3665 return;
3666
3667 // PHI nodes are modeled as if they had been demoted prior to the SCoP
3668 // detection. Hence, the PHI is a load of a new memory location in which the
3669 // incoming value was written at the end of the incoming basic block.
3670 bool OnlyNonAffineSubRegionOperands = true;
3671 for (unsigned u = 0; u < PHI->getNumIncomingValues(); u++) {
3672 Value *Op = PHI->getIncomingValue(u);
3673 BasicBlock *OpBB = PHI->getIncomingBlock(u);
3674
3675 // Do not build scalar dependences inside a non-affine subregion.
3676 if (NonAffineSubRegion && NonAffineSubRegion->contains(OpBB))
3677 continue;
3678
3679 OnlyNonAffineSubRegionOperands = false;
Michael Kruseee6a4fc2016-01-26 13:33:27 +00003680 ensurePHIWrite(PHI, OpBB, Op, IsExitBlock);
Michael Kruse7bf39442015-09-10 12:46:52 +00003681 }
3682
Michael Kruse33d6c0b2015-09-25 18:53:27 +00003683 if (!OnlyNonAffineSubRegionOperands && !IsExitBlock) {
3684 addPHIReadAccess(PHI);
Michael Kruse7bf39442015-09-10 12:46:52 +00003685 }
3686}
3687
Michael Kruse2e02d562016-02-06 09:19:40 +00003688void ScopInfo::buildScalarDependences(Instruction *Inst) {
3689 assert(!isa<PHINode>(Inst));
Michael Kruse7bf39442015-09-10 12:46:52 +00003690
Michael Kruse2e02d562016-02-06 09:19:40 +00003691 // Pull-in required operands.
3692 for (Use &Op : Inst->operands())
3693 ensureValueRead(Op.get(), Inst->getParent());
3694}
Michael Kruse7bf39442015-09-10 12:46:52 +00003695
Michael Kruse2e02d562016-02-06 09:19:40 +00003696void ScopInfo::buildEscapingDependences(Instruction *Inst) {
3697 Region *R = &scop->getRegion();
Michael Kruse7bf39442015-09-10 12:46:52 +00003698
Michael Kruse2e02d562016-02-06 09:19:40 +00003699 // Check for uses of this instruction outside the scop. Because we do not
3700 // iterate over such instructions and therefore did not "ensure" the existence
3701 // of a write, we must determine such use here.
3702 for (Use &U : Inst->uses()) {
3703 Instruction *UI = dyn_cast<Instruction>(U.getUser());
3704 if (!UI)
Michael Kruse7bf39442015-09-10 12:46:52 +00003705 continue;
3706
Michael Kruse2e02d562016-02-06 09:19:40 +00003707 BasicBlock *UseParent = getUseBlock(U);
3708 BasicBlock *UserParent = UI->getParent();
Michael Kruse7bf39442015-09-10 12:46:52 +00003709
Michael Kruse2e02d562016-02-06 09:19:40 +00003710 // An escaping value is either used by an instruction not within the scop,
3711 // or (when the scop region's exit needs to be simplified) by a PHI in the
3712 // scop's exit block. This is because region simplification before code
3713 // generation inserts new basic blocks before the PHI such that its incoming
3714 // blocks are not in the scop anymore.
3715 if (!R->contains(UseParent) ||
3716 (isa<PHINode>(UI) && UserParent == R->getExit() &&
3717 R->getExitingBlock())) {
3718 // At least one escaping use found.
3719 ensureValueWrite(Inst);
3720 break;
Michael Kruse7bf39442015-09-10 12:46:52 +00003721 }
3722 }
Michael Kruse7bf39442015-09-10 12:46:52 +00003723}
3724
3725extern MapInsnToMemAcc InsnToMemAcc;
3726
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003727bool ScopInfo::buildAccessMultiDimFixed(
Michael Kruse70131d32016-01-27 17:09:17 +00003728 MemAccInst Inst, Loop *L, Region *R,
Johannes Doerfert09e36972015-10-07 20:17:36 +00003729 const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
3730 const InvariantLoadsSetTy &ScopRIL) {
Michael Kruse70131d32016-01-27 17:09:17 +00003731 Value *Val = Inst.getValueOperand();
3732 Type *SizeType = Val->getType();
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003733 unsigned ElementSize = DL->getTypeAllocSize(SizeType);
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003734 Value *Address = Inst.getPointerOperand();
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003735 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L);
Michael Kruse7bf39442015-09-10 12:46:52 +00003736 const SCEVUnknown *BasePointer =
3737 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003738 enum MemoryAccess::AccessType Type =
3739 Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
Michael Kruse7bf39442015-09-10 12:46:52 +00003740
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003741 if (isa<GetElementPtrInst>(Address) || isa<BitCastInst>(Address)) {
3742 auto NewAddress = Address;
3743 if (auto *BitCast = dyn_cast<BitCastInst>(Address)) {
3744 auto Src = BitCast->getOperand(0);
3745 auto SrcTy = Src->getType();
3746 auto DstTy = BitCast->getType();
3747 if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits())
3748 NewAddress = Src;
3749 }
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003750
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003751 if (auto *GEP = dyn_cast<GetElementPtrInst>(NewAddress)) {
3752 std::vector<const SCEV *> Subscripts;
3753 std::vector<int> Sizes;
3754 std::tie(Subscripts, Sizes) = getIndexExpressionsFromGEP(GEP, *SE);
3755 auto BasePtr = GEP->getOperand(0);
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003756
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003757 std::vector<const SCEV *> SizesSCEV;
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003758
Johannes Doerfert09e36972015-10-07 20:17:36 +00003759 for (auto Subscript : Subscripts) {
3760 InvariantLoadsSetTy AccessILS;
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003761 if (!isAffineExpr(R, Subscript, *SE, nullptr, &AccessILS))
3762 return false;
Johannes Doerfert09e36972015-10-07 20:17:36 +00003763
3764 for (LoadInst *LInst : AccessILS)
3765 if (!ScopRIL.count(LInst))
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003766 return false;
Johannes Doerfert09e36972015-10-07 20:17:36 +00003767 }
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003768
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003769 if (Sizes.size() > 0) {
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003770 for (auto V : Sizes)
3771 SizesSCEV.push_back(SE->getSCEV(ConstantInt::get(
3772 IntegerType::getInt64Ty(BasePtr->getContext()), V)));
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003773
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003774 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementSize, true,
Tobias Grossera535dff2015-12-13 19:59:01 +00003775 Subscripts, SizesSCEV, Val);
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003776 return true;
Tobias Grosser6f36d9a2015-09-17 20:16:21 +00003777 }
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003778 }
3779 }
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003780 return false;
3781}
3782
3783bool ScopInfo::buildAccessMultiDimParam(
3784 MemAccInst Inst, Loop *L, Region *R,
3785 const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
3786 const InvariantLoadsSetTy &ScopRIL) {
3787 Value *Address = Inst.getPointerOperand();
3788 Value *Val = Inst.getValueOperand();
3789 Type *SizeType = Val->getType();
3790 unsigned ElementSize = DL->getTypeAllocSize(SizeType);
3791 enum MemoryAccess::AccessType Type =
3792 Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
3793
3794 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L);
3795 const SCEVUnknown *BasePointer =
3796 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
3797
3798 assert(BasePointer && "Could not find base pointer");
3799 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
Tobias Grosser5fd8c092015-09-17 17:28:15 +00003800
Michael Kruse7bf39442015-09-10 12:46:52 +00003801 auto AccItr = InsnToMemAcc.find(Inst);
Michael Krusee2bccbb2015-09-18 19:59:43 +00003802 if (PollyDelinearize && AccItr != InsnToMemAcc.end()) {
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003803 std::vector<const SCEV *> Sizes(
3804 AccItr->second.Shape->DelinearizedSizes.begin(),
3805 AccItr->second.Shape->DelinearizedSizes.end());
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003806 // Remove the element size. This information is already provided by the
Tobias Grosserd840fc72016-02-04 13:18:42 +00003807 // ElementSize parameter. In case the element size of this access and the
3808 // element size used for delinearization differs the delinearization is
3809 // incorrect. Hence, we invalidate the scop.
3810 //
3811 // TODO: Handle delinearization with differing element sizes.
3812 auto DelinearizedSize =
3813 cast<SCEVConstant>(Sizes.back())->getAPInt().getSExtValue();
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003814 Sizes.pop_back();
Tobias Grosserd840fc72016-02-04 13:18:42 +00003815 if (ElementSize != DelinearizedSize)
3816 scop->invalidate(DELINEARIZATION, Inst.getDebugLoc());
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003817
3818 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementSize, true,
3819 AccItr->second.DelinearizedSubscripts, Sizes, Val);
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003820 return true;
Michael Krusee2bccbb2015-09-18 19:59:43 +00003821 }
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003822 return false;
3823}
3824
3825void ScopInfo::buildAccessSingleDim(
3826 MemAccInst Inst, Loop *L, Region *R,
3827 const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
3828 const InvariantLoadsSetTy &ScopRIL) {
3829 Value *Address = Inst.getPointerOperand();
3830 Value *Val = Inst.getValueOperand();
3831 Type *SizeType = Val->getType();
3832 unsigned ElementSize = DL->getTypeAllocSize(SizeType);
3833 enum MemoryAccess::AccessType Type =
3834 Inst.isLoad() ? MemoryAccess::READ : MemoryAccess::MUST_WRITE;
3835
3836 const SCEV *AccessFunction = SE->getSCEVAtScope(Address, L);
3837 const SCEVUnknown *BasePointer =
3838 dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
3839
3840 assert(BasePointer && "Could not find base pointer");
3841 AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
Michael Kruse7bf39442015-09-10 12:46:52 +00003842
3843 // Check if the access depends on a loop contained in a non-affine subregion.
3844 bool isVariantInNonAffineLoop = false;
3845 if (BoxedLoops) {
3846 SetVector<const Loop *> Loops;
3847 findLoops(AccessFunction, Loops);
3848 for (const Loop *L : Loops)
3849 if (BoxedLoops->count(L))
3850 isVariantInNonAffineLoop = true;
3851 }
3852
Johannes Doerfert09e36972015-10-07 20:17:36 +00003853 InvariantLoadsSetTy AccessILS;
3854 bool IsAffine =
3855 !isVariantInNonAffineLoop &&
3856 isAffineExpr(R, AccessFunction, *SE, BasePointer->getValue(), &AccessILS);
3857
3858 for (LoadInst *LInst : AccessILS)
3859 if (!ScopRIL.count(LInst))
3860 IsAffine = false;
Michael Kruse7bf39442015-09-10 12:46:52 +00003861
Michael Krusee2bccbb2015-09-18 19:59:43 +00003862 if (!IsAffine && Type == MemoryAccess::MUST_WRITE)
3863 Type = MemoryAccess::MAY_WRITE;
Michael Kruse7bf39442015-09-10 12:46:52 +00003864
Tobias Grosser5d51afe2016-02-02 16:46:45 +00003865 addArrayAccess(Inst, Type, BasePointer->getValue(), ElementSize, IsAffine,
3866 {AccessFunction}, {}, Val);
Michael Kruse7bf39442015-09-10 12:46:52 +00003867}
3868
Tobias Grosserdb543ed2016-02-02 16:46:49 +00003869void ScopInfo::buildMemoryAccess(
3870 MemAccInst Inst, Loop *L, Region *R,
3871 const ScopDetection::BoxedLoopsSetTy *BoxedLoops,
3872 const InvariantLoadsSetTy &ScopRIL) {
3873
3874 if (buildAccessMultiDimFixed(Inst, L, R, BoxedLoops, ScopRIL))
3875 return;
3876
3877 if (buildAccessMultiDimParam(Inst, L, R, BoxedLoops, ScopRIL))
3878 return;
3879
3880 buildAccessSingleDim(Inst, L, R, BoxedLoops, ScopRIL);
3881}
3882
Michael Krused868b5d2015-09-10 15:25:24 +00003883void ScopInfo::buildAccessFunctions(Region &R, Region &SR) {
Michael Kruse7bf39442015-09-10 12:46:52 +00003884
3885 if (SD->isNonAffineSubRegion(&SR, &R)) {
3886 for (BasicBlock *BB : SR.blocks())
3887 buildAccessFunctions(R, *BB, &SR);
3888 return;
3889 }
3890
3891 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
3892 if (I->isSubRegion())
3893 buildAccessFunctions(R, *I->getNodeAs<Region>());
3894 else
3895 buildAccessFunctions(R, *I->getNodeAs<BasicBlock>());
3896}
3897
Johannes Doerferta8781032016-02-02 14:14:40 +00003898void ScopInfo::buildStmts(Region &R, Region &SR) {
Michael Krusecac948e2015-10-02 13:53:07 +00003899
Johannes Doerferta8781032016-02-02 14:14:40 +00003900 if (SD->isNonAffineSubRegion(&SR, &R)) {
Michael Krusecac948e2015-10-02 13:53:07 +00003901 scop->addScopStmt(nullptr, &SR);
3902 return;
3903 }
3904
3905 for (auto I = SR.element_begin(), E = SR.element_end(); I != E; ++I)
3906 if (I->isSubRegion())
Johannes Doerferta8781032016-02-02 14:14:40 +00003907 buildStmts(R, *I->getNodeAs<Region>());
Michael Krusecac948e2015-10-02 13:53:07 +00003908 else
3909 scop->addScopStmt(I->getNodeAs<BasicBlock>(), nullptr);
3910}
3911
Michael Krused868b5d2015-09-10 15:25:24 +00003912void ScopInfo::buildAccessFunctions(Region &R, BasicBlock &BB,
3913 Region *NonAffineSubRegion,
3914 bool IsExitBlock) {
Tobias Grosser910cf262015-11-11 20:15:49 +00003915 // We do not build access functions for error blocks, as they may contain
3916 // instructions we can not model.
Johannes Doerfertc36d39b2016-02-02 14:14:20 +00003917 if (isErrorBlock(BB, R, *LI, *DT) && !IsExitBlock)
Tobias Grosser910cf262015-11-11 20:15:49 +00003918 return;
3919
Michael Kruse7bf39442015-09-10 12:46:52 +00003920 Loop *L = LI->getLoopFor(&BB);
3921
3922 // The set of loops contained in non-affine subregions that are part of R.
3923 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD->getBoxedLoops(&R);
3924
Johannes Doerfert09e36972015-10-07 20:17:36 +00003925 // The set of loads that are required to be invariant.
3926 auto &ScopRIL = *SD->getRequiredInvariantLoads(&R);
3927
Michael Kruse2e02d562016-02-06 09:19:40 +00003928 for (Instruction &Inst : BB) {
3929 PHINode *PHI = dyn_cast<PHINode>(&Inst);
Michael Kruse7bf39442015-09-10 12:46:52 +00003930 if (PHI)
Michael Krusee2bccbb2015-09-18 19:59:43 +00003931 buildPHIAccesses(PHI, R, NonAffineSubRegion, IsExitBlock);
Michael Kruse7bf39442015-09-10 12:46:52 +00003932
3933 // For the exit block we stop modeling after the last PHI node.
3934 if (!PHI && IsExitBlock)
3935 break;
3936
Johannes Doerfert09e36972015-10-07 20:17:36 +00003937 // TODO: At this point we only know that elements of ScopRIL have to be
3938 // invariant and will be hoisted for the SCoP to be processed. Though,
3939 // there might be other invariant accesses that will be hoisted and
3940 // that would allow to make a non-affine access affine.
Michael Kruse70131d32016-01-27 17:09:17 +00003941 if (auto MemInst = MemAccInst::dyn_cast(Inst))
3942 buildMemoryAccess(MemInst, L, &R, BoxedLoops, ScopRIL);
Michael Kruse7bf39442015-09-10 12:46:52 +00003943
Michael Kruse2e02d562016-02-06 09:19:40 +00003944 if (isIgnoredIntrinsic(&Inst))
Michael Kruse7bf39442015-09-10 12:46:52 +00003945 continue;
3946
Michael Kruse2e02d562016-02-06 09:19:40 +00003947 if (!PHI)
3948 buildScalarDependences(&Inst);
3949 if (!IsExitBlock)
3950 buildEscapingDependences(&Inst);
Michael Kruse7bf39442015-09-10 12:46:52 +00003951 }
Michael Krusee2bccbb2015-09-18 19:59:43 +00003952}
Michael Kruse7bf39442015-09-10 12:46:52 +00003953
Michael Kruseee6a4fc2016-01-26 13:33:27 +00003954MemoryAccess *ScopInfo::addMemoryAccess(BasicBlock *BB, Instruction *Inst,
3955 MemoryAccess::AccessType Type,
3956 Value *BaseAddress, unsigned ElemBytes,
3957 bool Affine, Value *AccessValue,
3958 ArrayRef<const SCEV *> Subscripts,
3959 ArrayRef<const SCEV *> Sizes,
3960 ScopArrayInfo::MemoryKind Kind) {
Michael Krusecac948e2015-10-02 13:53:07 +00003961 ScopStmt *Stmt = scop->getStmtForBasicBlock(BB);
3962
3963 // Do not create a memory access for anything not in the SCoP. It would be
3964 // ignored anyway.
3965 if (!Stmt)
Michael Kruseee6a4fc2016-01-26 13:33:27 +00003966 return nullptr;
Michael Krusecac948e2015-10-02 13:53:07 +00003967
Michael Krusee2bccbb2015-09-18 19:59:43 +00003968 AccFuncSetType &AccList = AccFuncMap[BB];
Michael Krusee2bccbb2015-09-18 19:59:43 +00003969 Value *BaseAddr = BaseAddress;
3970 std::string BaseName = getIslCompatibleName("MemRef_", BaseAddr, "");
3971
Tobias Grosserf4f68702015-12-14 15:05:37 +00003972 bool isKnownMustAccess = false;
3973
3974 // Accesses in single-basic block statements are always excuted.
3975 if (Stmt->isBlockStmt())
3976 isKnownMustAccess = true;
3977
3978 if (Stmt->isRegionStmt()) {
3979 // Accesses that dominate the exit block of a non-affine region are always
3980 // executed. In non-affine regions there may exist MK_Values that do not
3981 // dominate the exit. MK_Values will always dominate the exit and MK_PHIs
3982 // only if there is at most one PHI_WRITE in the non-affine region.
3983 if (DT->dominates(BB, Stmt->getRegion()->getExit()))
3984 isKnownMustAccess = true;
3985 }
3986
Michael Kruseee6a4fc2016-01-26 13:33:27 +00003987 // Non-affine PHI writes do not "happen" at a particular instruction, but
3988 // after exiting the statement. Therefore they are guaranteed execute and
3989 // overwrite the old value.
3990 if (Kind == ScopArrayInfo::MK_PHI || Kind == ScopArrayInfo::MK_ExitPHI)
3991 isKnownMustAccess = true;
3992
Tobias Grosserf4f68702015-12-14 15:05:37 +00003993 if (!isKnownMustAccess && Type == MemoryAccess::MUST_WRITE)
Michael Krusecac948e2015-10-02 13:53:07 +00003994 Type = MemoryAccess::MAY_WRITE;
3995
Tobias Grosserf1bfd752015-11-05 20:15:37 +00003996 AccList.emplace_back(Stmt, Inst, Type, BaseAddress, ElemBytes, Affine,
Tobias Grossera535dff2015-12-13 19:59:01 +00003997 Subscripts, Sizes, AccessValue, Kind, BaseName);
Michael Krusecac948e2015-10-02 13:53:07 +00003998 Stmt->addAccess(&AccList.back());
Michael Kruseee6a4fc2016-01-26 13:33:27 +00003999 return &AccList.back();
Michael Kruse7bf39442015-09-10 12:46:52 +00004000}
4001
Michael Kruse70131d32016-01-27 17:09:17 +00004002void ScopInfo::addArrayAccess(MemAccInst MemAccInst,
Tobias Grossera535dff2015-12-13 19:59:01 +00004003 MemoryAccess::AccessType Type, Value *BaseAddress,
4004 unsigned ElemBytes, bool IsAffine,
4005 ArrayRef<const SCEV *> Subscripts,
4006 ArrayRef<const SCEV *> Sizes,
4007 Value *AccessValue) {
Michael Kruse70131d32016-01-27 17:09:17 +00004008 assert(MemAccInst.isLoad() == (Type == MemoryAccess::READ));
4009 addMemoryAccess(MemAccInst.getParent(), MemAccInst, Type, BaseAddress,
Michael Kruse8d0b7342015-09-25 21:21:00 +00004010 ElemBytes, IsAffine, AccessValue, Subscripts, Sizes,
Tobias Grossera535dff2015-12-13 19:59:01 +00004011 ScopArrayInfo::MK_Array);
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004012}
Michael Kruse436db622016-01-26 13:33:10 +00004013void ScopInfo::ensureValueWrite(Instruction *Value) {
4014 ScopStmt *Stmt = scop->getStmtForBasicBlock(Value->getParent());
4015
4016 // Value not defined within this SCoP.
4017 if (!Stmt)
4018 return;
4019
4020 // Do not process further if the value is already written.
4021 if (Stmt->lookupValueWriteOf(Value))
4022 return;
4023
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004024 addMemoryAccess(Value->getParent(), Value, MemoryAccess::MUST_WRITE, Value, 1,
4025 true, Value, ArrayRef<const SCEV *>(),
Tobias Grossera535dff2015-12-13 19:59:01 +00004026 ArrayRef<const SCEV *>(), ScopArrayInfo::MK_Value);
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004027}
Michael Krusead28e5a2016-01-26 13:33:15 +00004028void ScopInfo::ensureValueRead(Value *Value, BasicBlock *UserBB) {
Michael Krusefd463082016-01-27 22:51:56 +00004029
Michael Kruse2e02d562016-02-06 09:19:40 +00004030 // There cannot be an "access" for literal constants. BasicBlock references
4031 // (jump destinations) also never change.
4032 if ((isa<Constant>(Value) && !isa<GlobalVariable>(Value)) ||
4033 isa<BasicBlock>(Value))
4034 return;
4035
Michael Krusefd463082016-01-27 22:51:56 +00004036 // If the instruction can be synthesized and the user is in the region we do
4037 // not need to add a value dependences.
4038 Region &ScopRegion = scop->getRegion();
4039 if (canSynthesize(Value, LI, SE, &ScopRegion))
4040 return;
4041
Michael Kruse2e02d562016-02-06 09:19:40 +00004042 // Do not build scalar dependences for required invariant loads as we will
4043 // hoist them later on anyway or drop the SCoP if we cannot.
4044 auto ScopRIL = SD->getRequiredInvariantLoads(&ScopRegion);
4045 if (ScopRIL->count(dyn_cast<LoadInst>(Value)))
4046 return;
4047
4048 // Determine the ScopStmt containing the value's definition and use. There is
4049 // no defining ScopStmt if the value is a function argument, a global value,
4050 // or defined outside the SCoP.
4051 Instruction *ValueInst = dyn_cast<Instruction>(Value);
4052 ScopStmt *ValueStmt =
4053 ValueInst ? scop->getStmtForBasicBlock(ValueInst->getParent()) : nullptr;
4054
Michael Krusead28e5a2016-01-26 13:33:15 +00004055 ScopStmt *UserStmt = scop->getStmtForBasicBlock(UserBB);
4056
4057 // We do not model uses outside the scop.
4058 if (!UserStmt)
4059 return;
4060
Michael Kruse2e02d562016-02-06 09:19:40 +00004061 // Add MemoryAccess for invariant values only if requested.
4062 if (!ModelReadOnlyScalars && !ValueStmt)
4063 return;
4064
4065 // Ignore use-def chains within the same ScopStmt.
4066 if (ValueStmt == UserStmt)
4067 return;
4068
Michael Krusead28e5a2016-01-26 13:33:15 +00004069 // Do not create another MemoryAccess for reloading the value if one already
4070 // exists.
4071 if (UserStmt->lookupValueReadOf(Value))
4072 return;
4073
4074 addMemoryAccess(UserBB, nullptr, MemoryAccess::READ, Value, 1, true, Value,
Michael Kruse8d0b7342015-09-25 21:21:00 +00004075 ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
Tobias Grossera535dff2015-12-13 19:59:01 +00004076 ScopArrayInfo::MK_Value);
Michael Kruse2e02d562016-02-06 09:19:40 +00004077 if (ValueInst)
4078 ensureValueWrite(ValueInst);
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004079}
Michael Kruseee6a4fc2016-01-26 13:33:27 +00004080void ScopInfo::ensurePHIWrite(PHINode *PHI, BasicBlock *IncomingBlock,
4081 Value *IncomingValue, bool IsExitBlock) {
4082 ScopStmt *IncomingStmt = scop->getStmtForBasicBlock(IncomingBlock);
Michael Kruse2e02d562016-02-06 09:19:40 +00004083 if (!IncomingStmt)
4084 return;
4085
4086 // Take care for the incoming value being available in the incoming block.
4087 // This must be done before the check for multiple PHI writes because multiple
4088 // exiting edges from subregion each can be the effective written value of the
4089 // subregion. As such, all of them must be made available in the subregion
4090 // statement.
4091 ensureValueRead(IncomingValue, IncomingBlock);
Michael Kruseee6a4fc2016-01-26 13:33:27 +00004092
4093 // Do not add more than one MemoryAccess per PHINode and ScopStmt.
4094 if (MemoryAccess *Acc = IncomingStmt->lookupPHIWriteOf(PHI)) {
4095 assert(Acc->getAccessInstruction() == PHI);
4096 Acc->addIncoming(IncomingBlock, IncomingValue);
4097 return;
4098 }
4099
4100 MemoryAccess *Acc = addMemoryAccess(
4101 IncomingStmt->isBlockStmt() ? IncomingBlock
4102 : IncomingStmt->getRegion()->getEntry(),
4103 PHI, MemoryAccess::MUST_WRITE, PHI, 1, true, PHI,
4104 ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
4105 IsExitBlock ? ScopArrayInfo::MK_ExitPHI : ScopArrayInfo::MK_PHI);
4106 assert(Acc);
4107 Acc->addIncoming(IncomingBlock, IncomingValue);
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004108}
4109void ScopInfo::addPHIReadAccess(PHINode *PHI) {
4110 addMemoryAccess(PHI->getParent(), PHI, MemoryAccess::READ, PHI, 1, true, PHI,
Michael Kruse8d0b7342015-09-25 21:21:00 +00004111 ArrayRef<const SCEV *>(), ArrayRef<const SCEV *>(),
Tobias Grossera535dff2015-12-13 19:59:01 +00004112 ScopArrayInfo::MK_PHI);
Michael Kruse33d6c0b2015-09-25 18:53:27 +00004113}
4114
Michael Krusedaf66942015-12-13 22:10:37 +00004115void ScopInfo::buildScop(Region &R, AssumptionCache &AC) {
Michael Kruse9d080092015-09-11 21:41:48 +00004116 unsigned MaxLoopDepth = getMaxLoopDepthInRegion(R, *LI, *SD);
Michael Krusedaf66942015-12-13 22:10:37 +00004117 scop = new Scop(R, AccFuncMap, *SD, *SE, *DT, *LI, ctx, MaxLoopDepth);
Michael Kruse7bf39442015-09-10 12:46:52 +00004118
Johannes Doerferta8781032016-02-02 14:14:40 +00004119 buildStmts(R, R);
Michael Kruse7bf39442015-09-10 12:46:52 +00004120 buildAccessFunctions(R, R);
4121
4122 // In case the region does not have an exiting block we will later (during
4123 // code generation) split the exit block. This will move potential PHI nodes
4124 // from the current exit block into the new region exiting block. Hence, PHI
4125 // nodes that are at this point not part of the region will be.
4126 // To handle these PHI nodes later we will now model their operands as scalar
4127 // accesses. Note that we do not model anything in the exit block if we have
4128 // an exiting block in the region, as there will not be any splitting later.
4129 if (!R.getExitingBlock())
4130 buildAccessFunctions(R, *R.getExit(), nullptr, /* IsExitBlock */ true);
4131
Johannes Doerfert2af10e22015-11-12 03:25:01 +00004132 scop->init(*AA, AC);
Michael Kruse7bf39442015-09-10 12:46:52 +00004133}
4134
Michael Krused868b5d2015-09-10 15:25:24 +00004135void ScopInfo::print(raw_ostream &OS, const Module *) const {
Michael Kruse9d080092015-09-11 21:41:48 +00004136 if (!scop) {
Michael Krused868b5d2015-09-10 15:25:24 +00004137 OS << "Invalid Scop!\n";
Michael Kruse9d080092015-09-11 21:41:48 +00004138 return;
4139 }
4140
Michael Kruse9d080092015-09-11 21:41:48 +00004141 scop->print(OS);
Michael Kruse7bf39442015-09-10 12:46:52 +00004142}
4143
Michael Krused868b5d2015-09-10 15:25:24 +00004144void ScopInfo::clear() {
Michael Kruse7bf39442015-09-10 12:46:52 +00004145 AccFuncMap.clear();
Michael Krused868b5d2015-09-10 15:25:24 +00004146 if (scop) {
4147 delete scop;
4148 scop = 0;
4149 }
Michael Kruse7bf39442015-09-10 12:46:52 +00004150}
4151
4152//===----------------------------------------------------------------------===//
Michael Kruse9d080092015-09-11 21:41:48 +00004153ScopInfo::ScopInfo() : RegionPass(ID), scop(0) {
Tobias Grosserb76f38532011-08-20 11:11:25 +00004154 ctx = isl_ctx_alloc();
Tobias Grosser4a8e3562011-12-07 07:42:51 +00004155 isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
Tobias Grosserb76f38532011-08-20 11:11:25 +00004156}
4157
4158ScopInfo::~ScopInfo() {
4159 clear();
4160 isl_ctx_free(ctx);
4161}
4162
Tobias Grosser75805372011-04-29 06:27:02 +00004163void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
Chandler Carruthf5579872015-01-17 14:16:56 +00004164 AU.addRequired<LoopInfoWrapperPass>();
Matt Arsenault8ca36812014-07-19 18:40:17 +00004165 AU.addRequired<RegionInfoPass>();
Johannes Doerfert96425c22015-08-30 21:13:53 +00004166 AU.addRequired<DominatorTreeWrapperPass>();
Michael Krused868b5d2015-09-10 15:25:24 +00004167 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
4168 AU.addRequiredTransitive<ScopDetection>();
Chandler Carruth66ef16b2015-09-09 22:13:56 +00004169 AU.addRequired<AAResultsWrapperPass>();
Johannes Doerfert2af10e22015-11-12 03:25:01 +00004170 AU.addRequired<AssumptionCacheTracker>();
Tobias Grosser75805372011-04-29 06:27:02 +00004171 AU.setPreservesAll();
4172}
4173
4174bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
Michael Krused868b5d2015-09-10 15:25:24 +00004175 SD = &getAnalysis<ScopDetection>();
Tobias Grosser75805372011-04-29 06:27:02 +00004176
Michael Krused868b5d2015-09-10 15:25:24 +00004177 if (!SD->isMaxRegionInScop(*R))
4178 return false;
4179
4180 Function *F = R->getEntry()->getParent();
4181 SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
4182 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
4183 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Johannes Doerferta1f291e2016-02-02 14:15:13 +00004184 DL = &F->getParent()->getDataLayout();
Michael Krusedaf66942015-12-13 22:10:37 +00004185 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Johannes Doerfert2af10e22015-11-12 03:25:01 +00004186 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F);
Michael Krused868b5d2015-09-10 15:25:24 +00004187
Johannes Doerfert48fe86f2015-11-12 02:32:32 +00004188 DebugLoc Beg, End;
4189 getDebugLocations(R, Beg, End);
4190 std::string Msg = "SCoP begins here.";
4191 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, Msg);
4192
Michael Krusedaf66942015-12-13 22:10:37 +00004193 buildScop(*R, AC);
Tobias Grosser75805372011-04-29 06:27:02 +00004194
Tobias Grosserd6a50b32015-05-30 06:26:21 +00004195 DEBUG(scop->print(dbgs()));
4196
Michael Kruseafe06702015-10-02 16:33:27 +00004197 if (scop->isEmpty() || !scop->hasFeasibleRuntimeContext()) {
Johannes Doerfert48fe86f2015-11-12 02:32:32 +00004198 Msg = "SCoP ends here but was dismissed.";
Johannes Doerfert43788c52015-08-20 05:58:56 +00004199 delete scop;
4200 scop = nullptr;
Johannes Doerfert48fe86f2015-11-12 02:32:32 +00004201 } else {
4202 Msg = "SCoP ends here.";
4203 ++ScopFound;
4204 if (scop->getMaxLoopDepth() > 0)
4205 ++RichScopFound;
Johannes Doerfert43788c52015-08-20 05:58:56 +00004206 }
4207
Johannes Doerfert48fe86f2015-11-12 02:32:32 +00004208 emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, Msg);
4209
Tobias Grosser75805372011-04-29 06:27:02 +00004210 return false;
4211}
4212
4213char ScopInfo::ID = 0;
4214
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00004215Pass *polly::createScopInfoPass() { return new ScopInfo(); }
4216
Tobias Grosser73600b82011-10-08 00:30:40 +00004217INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops",
4218 "Polly - Create polyhedral description of Scops", false,
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00004219 false);
Chandler Carruth66ef16b2015-09-09 22:13:56 +00004220INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
Johannes Doerfert2af10e22015-11-12 03:25:01 +00004221INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker);
Chandler Carruthf5579872015-01-17 14:16:56 +00004222INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
Matt Arsenault8ca36812014-07-19 18:40:17 +00004223INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
Tobias Grosserc5bcf242015-08-17 10:57:08 +00004224INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00004225INITIALIZE_PASS_DEPENDENCY(ScopDetection);
Johannes Doerfert96425c22015-08-30 21:13:53 +00004226INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
Tobias Grosser73600b82011-10-08 00:30:40 +00004227INITIALIZE_PASS_END(ScopInfo, "polly-scops",
4228 "Polly - Create polyhedral description of Scops", false,
4229 false)