blob: 9244796a23c6c5e6d5ba557f875d1a09523878cf [file] [log] [blame]
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001//===- ScopInfo.cpp -------------------------------------------------------===//
Tobias Grosser75805372011-04-29 06:27:02 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Tobias Grosser75805372011-04-29 06:27:02 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Create a polyhedral description for a static control flow region.
10//
11// The pass creates a polyhedral description of the Scops detected by the Scop
12// detection derived from their LLVM-IR code.
13//
Tobias Grossera5605d32014-10-29 19:58:28 +000014// This representation is shared among several tools in the polyhedral
Tobias Grosser75805372011-04-29 06:27:02 +000015// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
16//
17//===----------------------------------------------------------------------===//
18
Tobias Grosser5624d3c2015-12-21 12:38:56 +000019#include "polly/ScopInfo.h"
Tobias Grosser75805372011-04-29 06:27:02 +000020#include "polly/LinkAllPasses.h"
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000021#include "polly/Options.h"
Michael Kruse73fa33b2016-06-28 01:37:28 +000022#include "polly/ScopBuilder.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000023#include "polly/ScopDetection.h"
Tobias Grosser75805372011-04-29 06:27:02 +000024#include "polly/Support/GICHelper.h"
Tobias Grosser77eef902017-07-21 23:07:56 +000025#include "polly/Support/ISLOStream.h"
Michael Krusee3300712018-05-09 16:23:56 +000026#include "polly/Support/ISLTools.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000027#include "polly/Support/SCEVAffinator.h"
Tobias Grosser60b54f12011-11-08 15:41:28 +000028#include "polly/Support/SCEVValidator.h"
Tobias Grosser83628182013-05-07 08:11:54 +000029#include "polly/Support/ScopHelper.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000030#include "llvm/ADT/APInt.h"
31#include "llvm/ADT/ArrayRef.h"
Tobias Grosserc2bb0cb2015-09-25 09:49:19 +000032#include "llvm/ADT/PostOrderIterator.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000033#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/ADT/SmallSet.h"
Tobias Grosser83628182013-05-07 08:11:54 +000035#include "llvm/ADT/Statistic.h"
Johannes Doerfertb164c792014-09-18 11:17:17 +000036#include "llvm/Analysis/AliasAnalysis.h"
Michael Kruse89b1f942017-03-17 13:56:53 +000037#include "llvm/Analysis/AssumptionCache.h"
Johannes Doerfert1dc12af2016-04-23 12:59:18 +000038#include "llvm/Analysis/Loads.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000039#include "llvm/Analysis/LoopInfo.h"
Adam Nemete0f15412017-10-09 23:49:08 +000040#include "llvm/Analysis/OptimizationRemarkEmitter.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000041#include "llvm/Analysis/RegionInfo.h"
Tobias Grosser83628182013-05-07 08:11:54 +000042#include "llvm/Analysis/RegionIterator.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000043#include "llvm/Analysis/ScalarEvolution.h"
Tobias Grosser83628182013-05-07 08:11:54 +000044#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000045#include "llvm/IR/BasicBlock.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000046#include "llvm/IR/ConstantRange.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000047#include "llvm/IR/DataLayout.h"
48#include "llvm/IR/DebugLoc.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000049#include "llvm/IR/Dominators.h"
50#include "llvm/IR/Function.h"
51#include "llvm/IR/InstrTypes.h"
52#include "llvm/IR/Instruction.h"
53#include "llvm/IR/Instructions.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000054#include "llvm/IR/Module.h"
55#include "llvm/IR/PassManager.h"
56#include "llvm/IR/Type.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000057#include "llvm/IR/Value.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000058#include "llvm/Support/Compiler.h"
Tobias Grosser75805372011-04-29 06:27:02 +000059#include "llvm/Support/Debug.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000060#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000061#include "llvm/Support/raw_ostream.h"
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000062#include "isl/aff.h"
Tobias Grosserf5338802011-10-06 00:03:35 +000063#include "isl/local_space.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000064#include "isl/map.h"
Tobias Grosser4a8e3562011-12-07 07:42:51 +000065#include "isl/options.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000066#include "isl/set.h"
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +000067#include <cassert>
Tobias Grosser75805372011-04-29 06:27:02 +000068
69using namespace llvm;
70using namespace polly;
71
Chandler Carruth95fef942014-04-22 03:30:19 +000072#define DEBUG_TYPE "polly-scops"
73
Johannes Doerfert81aa6e82016-11-18 14:37:08 +000074STATISTIC(AssumptionsAliasing, "Number of aliasing assumptions taken.");
75STATISTIC(AssumptionsInbounds, "Number of inbounds assumptions taken.");
76STATISTIC(AssumptionsWrapping, "Number of wrapping assumptions taken.");
77STATISTIC(AssumptionsUnsigned, "Number of unsigned assumptions taken.");
78STATISTIC(AssumptionsComplexity, "Number of too complex SCoPs.");
79STATISTIC(AssumptionsUnprofitable, "Number of unprofitable SCoPs.");
80STATISTIC(AssumptionsErrorBlock, "Number of error block assumptions taken.");
81STATISTIC(AssumptionsInfiniteLoop, "Number of bounded loop assumptions taken.");
82STATISTIC(AssumptionsInvariantLoad,
Johannes Doerfertcd195322016-11-17 21:41:08 +000083 "Number of invariant loads assumptions taken.");
Johannes Doerfert81aa6e82016-11-18 14:37:08 +000084STATISTIC(AssumptionsDelinearization,
Johannes Doerfertcd195322016-11-17 21:41:08 +000085 "Number of delinearization assumptions taken.");
86
Michael Kruse06ed5292017-08-23 13:50:30 +000087STATISTIC(NumScops, "Number of feasible SCoPs after ScopInfo");
Tobias Grossercd01a362017-02-17 08:12:36 +000088STATISTIC(NumLoopsInScop, "Number of loops in scops");
Michael Kruse06ed5292017-08-23 13:50:30 +000089STATISTIC(NumBoxedLoops, "Number of boxed loops in SCoPs after ScopInfo");
90STATISTIC(NumAffineLoops, "Number of affine loops in SCoPs after ScopInfo");
91
Tobias Grosserfcc3ad52018-04-18 20:03:36 +000092STATISTIC(NumScopsDepthZero, "Number of scops with maximal loop depth 0");
Tobias Grossercd01a362017-02-17 08:12:36 +000093STATISTIC(NumScopsDepthOne, "Number of scops with maximal loop depth 1");
94STATISTIC(NumScopsDepthTwo, "Number of scops with maximal loop depth 2");
95STATISTIC(NumScopsDepthThree, "Number of scops with maximal loop depth 3");
96STATISTIC(NumScopsDepthFour, "Number of scops with maximal loop depth 4");
97STATISTIC(NumScopsDepthFive, "Number of scops with maximal loop depth 5");
98STATISTIC(NumScopsDepthLarger,
99 "Number of scops with maximal loop depth 6 and larger");
100STATISTIC(MaxNumLoopsInScop, "Maximal number of loops in scops");
101
Michael Kruse06ed5292017-08-23 13:50:30 +0000102STATISTIC(NumValueWrites, "Number of scalar value writes after ScopInfo");
103STATISTIC(
104 NumValueWritesInLoops,
105 "Number of scalar value writes nested in affine loops after ScopInfo");
106STATISTIC(NumPHIWrites, "Number of scalar phi writes after ScopInfo");
107STATISTIC(NumPHIWritesInLoops,
108 "Number of scalar phi writes nested in affine loops after ScopInfo");
109STATISTIC(NumSingletonWrites, "Number of singleton writes after ScopInfo");
110STATISTIC(NumSingletonWritesInLoops,
111 "Number of singleton writes nested in affine loops after ScopInfo");
112
Michael Krusebb824c62019-06-12 22:40:08 +0000113int const polly::MaxDisjunctsInDomain = 20;
Tobias Grosser75dc40c2015-12-20 13:31:48 +0000114
Tobias Grosserc8a82762017-02-16 19:11:25 +0000115// The number of disjunct in the context after which we stop to add more
116// disjuncts. This parameter is there to avoid exponential growth in the
117// number of disjunct when adding non-convex sets to the context.
118static int const MaxDisjunctsInContext = 4;
119
Johannes Doerfert2f705842016-04-12 16:09:44 +0000120static cl::opt<bool> PollyRemarksMinimal(
121 "polly-remarks-minimal",
122 cl::desc("Do not emit remarks about assumptions that are known"),
123 cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory));
124
Tobias Grosser8a9c2352015-08-16 10:19:29 +0000125static cl::opt<std::string> UserContextStr(
126 "polly-context", cl::value_desc("isl parameter set"),
127 cl::desc("Provide additional constraints on the context parameters"),
128 cl::init(""), cl::cat(PollyCategory));
Tobias Grosser71500722015-03-28 15:11:14 +0000129
Tobias Grosser2937b592016-04-29 11:43:20 +0000130static cl::opt<bool>
131 IslOnErrorAbort("polly-on-isl-error-abort",
132 cl::desc("Abort if an isl error is encountered"),
133 cl::init(true), cl::cat(PollyCategory));
134
Tobias Grosserd7c49752017-02-28 09:45:54 +0000135static cl::opt<bool> PollyPreciseInbounds(
136 "polly-precise-inbounds",
137 cl::desc("Take more precise inbounds assumptions (do not scale well)"),
138 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
139
Tobias Grosser8a6e6052017-03-17 12:26:58 +0000140static cl::opt<bool>
141 PollyIgnoreInbounds("polly-ignore-inbounds",
142 cl::desc("Do not take inbounds assumptions at all"),
143 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
144
Tobias Grosser5842dee2017-03-17 13:00:53 +0000145static cl::opt<bool> PollyIgnoreParamBounds(
146 "polly-ignore-parameter-bounds",
147 cl::desc(
148 "Do not add parameter bounds and do no gist simplify sets accordingly"),
149 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
150
Tobias Grosserc2f15102017-03-01 21:11:27 +0000151static cl::opt<bool> PollyPreciseFoldAccesses(
152 "polly-precise-fold-accesses",
Michael Kruse6e7854a2017-04-03 12:03:38 +0000153 cl::desc("Fold memory accesses to model more possible delinearizations "
154 "(does not scale well)"),
Tobias Grosserc2f15102017-03-01 21:11:27 +0000155 cl::Hidden, cl::init(false), cl::cat(PollyCategory));
Tobias Grossere2ccc3f2017-05-03 20:08:52 +0000156
Michael Kruse5ae08c02017-05-06 14:03:58 +0000157bool polly::UseInstructionNames;
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000158
Michael Kruse5ae08c02017-05-06 14:03:58 +0000159static cl::opt<bool, true> XUseInstructionNames(
Tobias Grossere2ccc3f2017-05-03 20:08:52 +0000160 "polly-use-llvm-names",
Michael Kruse5ae08c02017-05-06 14:03:58 +0000161 cl::desc("Use LLVM-IR names when deriving statement names"),
162 cl::location(UseInstructionNames), cl::Hidden, cl::init(false),
163 cl::ZeroOrMore, cl::cat(PollyCategory));
Tobias Grossere2ccc3f2017-05-03 20:08:52 +0000164
Tobias Grosserd5fcbef2017-05-27 04:40:18 +0000165static cl::opt<bool> PollyPrintInstructions(
166 "polly-print-instructions", cl::desc("Output instructions per ScopStmt"),
167 cl::Hidden, cl::Optional, cl::init(false), cl::cat(PollyCategory));
168
Michael Kruse7bf39442015-09-10 12:46:52 +0000169//===----------------------------------------------------------------------===//
Michael Kruse7bf39442015-09-10 12:46:52 +0000170
Michael Kruse046dde42015-08-10 13:01:57 +0000171// Create a sequence of two schedules. Either argument may be null and is
172// interpreted as the empty schedule. Can also return null if both schedules are
173// empty.
Philip Pfaffe00fd43b2017-11-19 22:13:34 +0000174static isl::schedule combineInSequence(isl::schedule Prev, isl::schedule Succ) {
Michael Kruse046dde42015-08-10 13:01:57 +0000175 if (!Prev)
176 return Succ;
177 if (!Succ)
178 return Prev;
179
Philip Pfaffe00fd43b2017-11-19 22:13:34 +0000180 return Prev.sequence(Succ);
Michael Kruse046dde42015-08-10 13:01:57 +0000181}
182
Tobias Grosser99ea1d02017-05-21 20:23:20 +0000183static isl::set addRangeBoundsToSet(isl::set S, const ConstantRange &Range,
184 int dim, isl::dim type) {
185 isl::val V;
186 isl::ctx Ctx = S.get_ctx();
Johannes Doerferte7044942015-02-24 11:58:30 +0000187
Tobias Grosser3281f602017-02-16 18:39:14 +0000188 // The upper and lower bound for a parameter value is derived either from
189 // the data type of the parameter or from the - possibly more restrictive -
190 // range metadata.
Tobias Grosser99ea1d02017-05-21 20:23:20 +0000191 V = valFromAPInt(Ctx.get(), Range.getSignedMin(), true);
192 S = S.lower_bound_val(type, dim, V);
193 V = valFromAPInt(Ctx.get(), Range.getSignedMax(), true);
194 S = S.upper_bound_val(type, dim, V);
Johannes Doerferte7044942015-02-24 11:58:30 +0000195
Tobias Grosser3281f602017-02-16 18:39:14 +0000196 if (Range.isFullSet())
197 return S;
198
Philip Pfaffe9375d572018-05-16 14:05:03 +0000199 if (S.n_basic_set() > MaxDisjunctsInContext)
Tobias Grosserc8a82762017-02-16 19:11:25 +0000200 return S;
201
Tobias Grosser3281f602017-02-16 18:39:14 +0000202 // In case of signed wrapping, we can refine the set of valid values by
203 // excluding the part not covered by the wrapping range.
204 if (Range.isSignWrappedSet()) {
Tobias Grosser99ea1d02017-05-21 20:23:20 +0000205 V = valFromAPInt(Ctx.get(), Range.getLower(), true);
206 isl::set SLB = S.lower_bound_val(type, dim, V);
Tobias Grosser3281f602017-02-16 18:39:14 +0000207
Tobias Grosser99ea1d02017-05-21 20:23:20 +0000208 V = valFromAPInt(Ctx.get(), Range.getUpper(), true);
209 V = V.sub_ui(1);
210 isl::set SUB = S.upper_bound_val(type, dim, V);
211 S = SLB.unite(SUB);
Tobias Grosser3281f602017-02-16 18:39:14 +0000212 }
Johannes Doerferte7044942015-02-24 11:58:30 +0000213
Tobias Grosser3281f602017-02-16 18:39:14 +0000214 return S;
Johannes Doerferte7044942015-02-24 11:58:30 +0000215}
216
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000217static const ScopArrayInfo *identifyBasePtrOriginSAI(Scop *S, Value *BasePtr) {
218 LoadInst *BasePtrLI = dyn_cast<LoadInst>(BasePtr);
219 if (!BasePtrLI)
220 return nullptr;
221
Johannes Doerfert952b5302016-05-23 12:40:48 +0000222 if (!S->contains(BasePtrLI))
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000223 return nullptr;
224
225 ScalarEvolution &SE = *S->getSE();
226
227 auto *OriginBaseSCEV =
228 SE.getPointerBase(SE.getSCEV(BasePtrLI->getPointerOperand()));
229 if (!OriginBaseSCEV)
230 return nullptr;
231
232 auto *OriginBaseSCEVUnknown = dyn_cast<SCEVUnknown>(OriginBaseSCEV);
233 if (!OriginBaseSCEVUnknown)
234 return nullptr;
235
Tobias Grosser6abc75a2015-11-10 17:31:31 +0000236 return S->getScopArrayInfo(OriginBaseSCEVUnknown->getValue(),
Tobias Grosser4d5a9172017-01-14 20:25:44 +0000237 MemoryKind::Array);
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000238}
239
Tobias Grosser27db02b2017-08-06 17:25:05 +0000240ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl::ctx Ctx,
Hongbin Zheng6aded2a2017-01-15 16:47:26 +0000241 ArrayRef<const SCEV *> Sizes, MemoryKind Kind,
Roman Gareevd7754a12016-07-30 09:25:51 +0000242 const DataLayout &DL, Scop *S,
243 const char *BaseName)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000244 : BasePtr(BasePtr), ElementType(ElementType), Kind(Kind), DL(DL), S(*S) {
Tobias Grosser92245222015-07-28 14:53:44 +0000245 std::string BasePtrName =
Tobias Grosser4d5a9172017-01-14 20:25:44 +0000246 BaseName ? BaseName
Tobias Grossere2ccc3f2017-05-03 20:08:52 +0000247 : getIslCompatibleName("MemRef", BasePtr, S->getNextArrayIdx(),
248 Kind == MemoryKind::PHI ? "__phi" : "",
249 UseInstructionNames);
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000250 Id = isl::id::alloc(Ctx, BasePtrName, this);
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000251
Johannes Doerfert3ff22212016-02-14 22:31:39 +0000252 updateSizes(Sizes);
Roman Gareevd7754a12016-07-30 09:25:51 +0000253
Tobias Grosser4d5a9172017-01-14 20:25:44 +0000254 if (!BasePtr || Kind != MemoryKind::Array) {
Roman Gareevd7754a12016-07-30 09:25:51 +0000255 BasePtrOriginSAI = nullptr;
256 return;
257 }
258
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000259 BasePtrOriginSAI = identifyBasePtrOriginSAI(S, BasePtr);
260 if (BasePtrOriginSAI)
261 const_cast<ScopArrayInfo *>(BasePtrOriginSAI)->addDerivedSAI(this);
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000262}
263
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000264ScopArrayInfo::~ScopArrayInfo() = default;
265
Tobias Grosser77eef902017-07-21 23:07:56 +0000266isl::space ScopArrayInfo::getSpace() const {
267 auto Space = isl::space(Id.get_ctx(), 0, getNumberOfDimensions());
268 Space = Space.set_tuple_id(isl::dim::set, Id);
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000269 return Space;
270}
271
Tobias Grosserfe74a7a2016-09-17 19:22:18 +0000272bool ScopArrayInfo::isReadOnly() {
Tobias Grosser5ab39ff2017-08-06 19:22:27 +0000273 isl::union_set WriteSet = S.getWrites().range();
Tobias Grosser77eef902017-07-21 23:07:56 +0000274 isl::space Space = getSpace();
Tobias Grosser2ade9862017-05-23 06:41:04 +0000275 WriteSet = WriteSet.extract_set(Space);
Tobias Grosserfe74a7a2016-09-17 19:22:18 +0000276
Tobias Grosser2ade9862017-05-23 06:41:04 +0000277 return bool(WriteSet.is_empty());
Tobias Grosserfe74a7a2016-09-17 19:22:18 +0000278}
279
Tobias Grosserf3adab42017-05-10 10:59:58 +0000280bool ScopArrayInfo::isCompatibleWith(const ScopArrayInfo *Array) const {
281 if (Array->getElementType() != getElementType())
282 return false;
283
284 if (Array->getNumberOfDimensions() != getNumberOfDimensions())
285 return false;
286
287 for (unsigned i = 0; i < getNumberOfDimensions(); i++)
288 if (Array->getDimensionSize(i) != getDimensionSize(i))
289 return false;
290
291 return true;
292}
293
Johannes Doerfert3ff22212016-02-14 22:31:39 +0000294void ScopArrayInfo::updateElementType(Type *NewElementType) {
295 if (NewElementType == ElementType)
296 return;
297
Tobias Grosserd840fc72016-02-04 13:18:42 +0000298 auto OldElementSize = DL.getTypeAllocSizeInBits(ElementType);
299 auto NewElementSize = DL.getTypeAllocSizeInBits(NewElementType);
300
Johannes Doerferta7920982016-02-25 14:08:48 +0000301 if (NewElementSize == OldElementSize || NewElementSize == 0)
Johannes Doerfert3ff22212016-02-14 22:31:39 +0000302 return;
Tobias Grosserd840fc72016-02-04 13:18:42 +0000303
Johannes Doerfert3ff22212016-02-14 22:31:39 +0000304 if (NewElementSize % OldElementSize == 0 && NewElementSize < OldElementSize) {
305 ElementType = NewElementType;
306 } else {
307 auto GCD = GreatestCommonDivisor64(NewElementSize, OldElementSize);
308 ElementType = IntegerType::get(ElementType->getContext(), GCD);
309 }
310}
311
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000312/// Make the ScopArrayInfo model a Fortran Array
313void ScopArrayInfo::applyAndSetFAD(Value *FAD) {
314 assert(FAD && "got invalid Fortran array descriptor");
315 if (this->FAD) {
316 assert(this->FAD == FAD &&
317 "receiving different array descriptors for same array");
318 return;
319 }
320
321 assert(DimensionSizesPw.size() > 0 && !DimensionSizesPw[0]);
322 assert(!this->FAD);
323 this->FAD = FAD;
324
Tobias Grosserb1ed3d92017-05-23 07:07:05 +0000325 isl::space Space(S.getIslCtx(), 1, 0);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000326
327 std::string param_name = getName();
328 param_name += "_fortranarr_size";
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000329 isl::id IdPwAff = isl::id::alloc(S.getIslCtx(), param_name, this);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000330
Tobias Grosserb1ed3d92017-05-23 07:07:05 +0000331 Space = Space.set_dim_id(isl::dim::param, 0, IdPwAff);
332 isl::pw_aff PwAff =
333 isl::aff::var_on_domain(isl::local_space(Space), isl::dim::param, 0);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000334
Tobias Grosser77eef902017-07-21 23:07:56 +0000335 DimensionSizesPw[0] = PwAff;
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000336}
337
Tobias Grosserbedef002016-12-02 08:10:56 +0000338bool ScopArrayInfo::updateSizes(ArrayRef<const SCEV *> NewSizes,
339 bool CheckConsistency) {
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000340 int SharedDims = std::min(NewSizes.size(), DimensionSizes.size());
341 int ExtraDimsNew = NewSizes.size() - SharedDims;
342 int ExtraDimsOld = DimensionSizes.size() - SharedDims;
Roman Gareevf5aff702016-09-12 17:08:31 +0000343
Tobias Grosserbedef002016-12-02 08:10:56 +0000344 if (CheckConsistency) {
345 for (int i = 0; i < SharedDims; i++) {
346 auto *NewSize = NewSizes[i + ExtraDimsNew];
347 auto *KnownSize = DimensionSizes[i + ExtraDimsOld];
348 if (NewSize && KnownSize && NewSize != KnownSize)
349 return false;
350 }
Tobias Grosser8286b832015-11-02 11:29:32 +0000351
Tobias Grosserbedef002016-12-02 08:10:56 +0000352 if (DimensionSizes.size() >= NewSizes.size())
353 return true;
354 }
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000355
356 DimensionSizes.clear();
357 DimensionSizes.insert(DimensionSizes.begin(), NewSizes.begin(),
358 NewSizes.end());
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000359 DimensionSizesPw.clear();
360 for (const SCEV *Expr : DimensionSizes) {
Roman Gareevf5aff702016-09-12 17:08:31 +0000361 if (!Expr) {
362 DimensionSizesPw.push_back(nullptr);
363 continue;
364 }
Tobias Grosser61bd3a42017-08-06 21:42:38 +0000365 isl::pw_aff Size = S.getPwAffOnly(Expr);
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000366 DimensionSizesPw.push_back(Size);
367 }
Tobias Grosser8286b832015-11-02 11:29:32 +0000368 return true;
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000369}
370
Tobias Grosser77eef902017-07-21 23:07:56 +0000371std::string ScopArrayInfo::getName() const { return Id.get_name(); }
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000372
373int ScopArrayInfo::getElemSizeInBytes() const {
Johannes Doerfert55b3d8b2015-11-12 20:15:08 +0000374 return DL.getTypeAllocSize(ElementType);
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000375}
376
Tobias Grosser77eef902017-07-21 23:07:56 +0000377isl::id ScopArrayInfo::getBasePtrId() const { return Id; }
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000378
Michael Kruse5d518462017-07-21 15:54:07 +0000379#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Michael Krusee1860132017-07-21 15:54:13 +0000380LLVM_DUMP_METHOD void ScopArrayInfo::dump() const { print(errs()); }
Michael Kruse5d518462017-07-21 15:54:07 +0000381#endif
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000382
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000383void ScopArrayInfo::print(raw_ostream &OS, bool SizeAsPwAff) const {
Tobias Grosser4ea2e072015-11-10 14:02:54 +0000384 OS.indent(8) << *getElementType() << " " << getName();
Roman Gareevf5aff702016-09-12 17:08:31 +0000385 unsigned u = 0;
Siddharth Bhatb7f68b82017-05-19 15:07:45 +0000386 // If this is a Fortran array, then we can print the outermost dimension
387 // as a isl_pw_aff even though there is no SCEV information.
388 bool IsOutermostSizeKnown = SizeAsPwAff && FAD;
389
390 if (!IsOutermostSizeKnown && getNumberOfDimensions() > 0 &&
391 !getDimensionSize(0)) {
Tobias Grosser4ea2e072015-11-10 14:02:54 +0000392 OS << "[*]";
Roman Gareevf5aff702016-09-12 17:08:31 +0000393 u++;
394 }
395 for (; u < getNumberOfDimensions(); u++) {
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000396 OS << "[";
397
Tobias Grosser26253842015-11-10 14:24:21 +0000398 if (SizeAsPwAff) {
Tobias Grosser77eef902017-07-21 23:07:56 +0000399 isl::pw_aff Size = getDimensionSizePw(u);
Tobias Grosser26253842015-11-10 14:24:21 +0000400 OS << " " << Size << " ";
Tobias Grosser26253842015-11-10 14:24:21 +0000401 } else {
402 OS << *getDimensionSize(u);
403 }
Tobias Grosserd46fd5e2015-08-12 15:27:16 +0000404
405 OS << "]";
406 }
407
Tobias Grosser4ea2e072015-11-10 14:02:54 +0000408 OS << ";";
409
Johannes Doerfert4eed5be2015-08-20 18:04:22 +0000410 if (BasePtrOriginSAI)
411 OS << " [BasePtrOrigin: " << BasePtrOriginSAI->getName() << "]";
412
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000413 OS << " // Element size " << getElemSizeInBytes() << "\n";
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000414}
415
416const ScopArrayInfo *
Tobias Grosser206e9e32017-07-24 16:22:27 +0000417ScopArrayInfo::getFromAccessFunction(isl::pw_multi_aff PMA) {
418 isl::id Id = PMA.get_tuple_id(isl::dim::out);
419 assert(!Id.is_null() && "Output dimension didn't have an ID");
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000420 return getFromId(Id);
421}
422
Tobias Grosser206e9e32017-07-24 16:22:27 +0000423const ScopArrayInfo *ScopArrayInfo::getFromId(isl::id Id) {
424 void *User = Id.get_user();
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000425 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000426 return SAI;
427}
428
Michael Kruse3b425ff2016-04-11 14:34:08 +0000429void MemoryAccess::wrapConstantDimensions() {
430 auto *SAI = getScopArrayInfo();
Tobias Grosser77eef902017-07-21 23:07:56 +0000431 isl::space ArraySpace = SAI->getSpace();
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000432 isl::ctx Ctx = ArraySpace.get_ctx();
Michael Kruse3b425ff2016-04-11 14:34:08 +0000433 unsigned DimsArray = SAI->getNumberOfDimensions();
434
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000435 isl::multi_aff DivModAff = isl::multi_aff::identity(
436 ArraySpace.map_from_domain_and_range(ArraySpace));
437 isl::local_space LArraySpace = isl::local_space(ArraySpace);
Michael Kruse3b425ff2016-04-11 14:34:08 +0000438
439 // Begin with last dimension, to iteratively carry into higher dimensions.
440 for (int i = DimsArray - 1; i > 0; i--) {
441 auto *DimSize = SAI->getDimensionSize(i);
442 auto *DimSizeCst = dyn_cast<SCEVConstant>(DimSize);
443
444 // This transformation is not applicable to dimensions with dynamic size.
445 if (!DimSizeCst)
446 continue;
447
Tobias Grosserca2cfd02017-02-17 04:48:52 +0000448 // This transformation is not applicable to dimensions of size zero.
449 if (DimSize->isZero())
450 continue;
451
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000452 isl::val DimSizeVal =
453 valFromAPInt(Ctx.get(), DimSizeCst->getAPInt(), false);
454 isl::aff Var = isl::aff::var_on_domain(LArraySpace, isl::dim::set, i);
455 isl::aff PrevVar =
456 isl::aff::var_on_domain(LArraySpace, isl::dim::set, i - 1);
Michael Kruse3b425ff2016-04-11 14:34:08 +0000457
458 // Compute: index % size
459 // Modulo must apply in the divide of the previous iteration, if any.
Tobias Grossercb0224a2017-08-06 15:56:45 +0000460 isl::aff Modulo = Var.mod(DimSizeVal);
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000461 Modulo = Modulo.pullback(DivModAff);
Michael Kruse3b425ff2016-04-11 14:34:08 +0000462
463 // Compute: floor(index / size)
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000464 isl::aff Divide = Var.div(isl::aff(LArraySpace, DimSizeVal));
465 Divide = Divide.floor();
466 Divide = Divide.add(PrevVar);
467 Divide = Divide.pullback(DivModAff);
Michael Kruse3b425ff2016-04-11 14:34:08 +0000468
469 // Apply Modulo and Divide.
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000470 DivModAff = DivModAff.set_aff(i, Modulo);
471 DivModAff = DivModAff.set_aff(i - 1, Divide);
Michael Kruse3b425ff2016-04-11 14:34:08 +0000472 }
473
474 // Apply all modulo/divides on the accesses.
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000475 isl::map Relation = AccessRelation;
Tobias Grosser3137f2c2017-05-21 20:23:23 +0000476 Relation = Relation.apply_range(isl::map::from_multi_aff(DivModAff));
477 Relation = Relation.detect_equalities();
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000478 AccessRelation = Relation;
Michael Kruse3b425ff2016-04-11 14:34:08 +0000479}
480
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000481void MemoryAccess::updateDimensionality() {
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000482 auto *SAI = getScopArrayInfo();
Tobias Grosser77eef902017-07-21 23:07:56 +0000483 isl::space ArraySpace = SAI->getSpace();
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000484 isl::space AccessSpace = AccessRelation.get_space().range();
Tobias Grosser7be82452017-05-21 20:38:33 +0000485 isl::ctx Ctx = ArraySpace.get_ctx();
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000486
Tobias Grosser7be82452017-05-21 20:38:33 +0000487 auto DimsArray = ArraySpace.dim(isl::dim::set);
488 auto DimsAccess = AccessSpace.dim(isl::dim::set);
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000489 auto DimsMissing = DimsArray - DimsAccess;
490
Michael Kruse375cb5f2016-02-24 22:08:24 +0000491 auto *BB = getStatement()->getEntryBlock();
Johannes Doerfertcea61932016-02-21 19:13:19 +0000492 auto &DL = BB->getModule()->getDataLayout();
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000493 unsigned ArrayElemSize = SAI->getElemSizeInBytes();
Johannes Doerfertcea61932016-02-21 19:13:19 +0000494 unsigned ElemBytes = DL.getTypeAllocSize(getElementType());
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000495
Tobias Grosser7be82452017-05-21 20:38:33 +0000496 isl::map Map = isl::map::from_domain_and_range(
497 isl::set::universe(AccessSpace), isl::set::universe(ArraySpace));
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000498
499 for (unsigned i = 0; i < DimsMissing; i++)
Tobias Grosser7be82452017-05-21 20:38:33 +0000500 Map = Map.fix_si(isl::dim::out, i, 0);
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000501
502 for (unsigned i = DimsMissing; i < DimsArray; i++)
Tobias Grosser7be82452017-05-21 20:38:33 +0000503 Map = Map.equate(isl::dim::in, i - DimsMissing, isl::dim::out, i);
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000504
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000505 AccessRelation = AccessRelation.apply_range(Map);
Roman Gareev10595a12016-01-08 14:01:59 +0000506
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000507 // For the non delinearized arrays, divide the access function of the last
508 // subscript by the size of the elements in the array.
509 //
510 // A stride one array access in C expressed as A[i] is expressed in
511 // LLVM-IR as something like A[i * elementsize]. This hides the fact that
512 // two subsequent values of 'i' index two values that are stored next to
513 // each other in memory. By this division we make this characteristic
514 // obvious again. If the base pointer was accessed with offsets not divisible
Tobias Grosser2219d152016-08-03 05:28:09 +0000515 // by the accesses element size, we will have chosen a smaller ArrayElemSize
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000516 // that divides the offsets of all accesses to this base pointer.
517 if (DimsAccess == 1) {
Tobias Grosser7be82452017-05-21 20:38:33 +0000518 isl::val V = isl::val(Ctx, ArrayElemSize);
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000519 AccessRelation = AccessRelation.floordiv_val(V);
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000520 }
521
Michael Kruse3b425ff2016-04-11 14:34:08 +0000522 // We currently do this only if we added at least one dimension, which means
523 // some dimension's indices have not been specified, an indicator that some
524 // index values have been added together.
525 // TODO: Investigate general usefulness; Effect on unit tests is to make index
526 // expressions more complicated.
527 if (DimsMissing)
528 wrapConstantDimensions();
529
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000530 if (!isAffine())
531 computeBoundsOnAccessRelation(ArrayElemSize);
532
Tobias Grosserd840fc72016-02-04 13:18:42 +0000533 // Introduce multi-element accesses in case the type loaded by this memory
534 // access is larger than the canonical element type of the array.
535 //
536 // An access ((float *)A)[i] to an array char *A is modeled as
537 // {[i] -> A[o] : 4 i <= o <= 4 i + 3
Tobias Grosserd840fc72016-02-04 13:18:42 +0000538 if (ElemBytes > ArrayElemSize) {
539 assert(ElemBytes % ArrayElemSize == 0 &&
540 "Loaded element size should be multiple of canonical element size");
Tobias Grosser7be82452017-05-21 20:38:33 +0000541 isl::map Map = isl::map::from_domain_and_range(
542 isl::set::universe(ArraySpace), isl::set::universe(ArraySpace));
Tobias Grosserd840fc72016-02-04 13:18:42 +0000543 for (unsigned i = 0; i < DimsArray - 1; i++)
Tobias Grosser7be82452017-05-21 20:38:33 +0000544 Map = Map.equate(isl::dim::in, i, isl::dim::out, i);
Tobias Grosserd840fc72016-02-04 13:18:42 +0000545
Tobias Grosser7be82452017-05-21 20:38:33 +0000546 isl::constraint C;
547 isl::local_space LS;
Tobias Grosserd840fc72016-02-04 13:18:42 +0000548
Tobias Grosser7be82452017-05-21 20:38:33 +0000549 LS = isl::local_space(Map.get_space());
Tobias Grosserd840fc72016-02-04 13:18:42 +0000550 int Num = ElemBytes / getScopArrayInfo()->getElemSizeInBytes();
551
Tobias Grosser7be82452017-05-21 20:38:33 +0000552 C = isl::constraint::alloc_inequality(LS);
553 C = C.set_constant_val(isl::val(Ctx, Num - 1));
554 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, 1);
555 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, -1);
556 Map = Map.add_constraint(C);
Tobias Grosserd840fc72016-02-04 13:18:42 +0000557
Tobias Grosser7be82452017-05-21 20:38:33 +0000558 C = isl::constraint::alloc_inequality(LS);
559 C = C.set_coefficient_si(isl::dim::in, DimsArray - 1, -1);
560 C = C.set_coefficient_si(isl::dim::out, DimsArray - 1, 1);
561 C = C.set_constant_val(isl::val(Ctx, 0));
562 Map = Map.add_constraint(C);
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000563 AccessRelation = AccessRelation.apply_range(Map);
Tobias Grosserd840fc72016-02-04 13:18:42 +0000564 }
Tobias Grosser99c70dd2015-09-26 08:55:54 +0000565}
566
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000567const std::string
568MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
569 switch (RT) {
570 case MemoryAccess::RT_NONE:
571 llvm_unreachable("Requested a reduction operator string for a memory "
572 "access which isn't a reduction");
573 case MemoryAccess::RT_ADD:
574 return "+";
575 case MemoryAccess::RT_MUL:
576 return "*";
577 case MemoryAccess::RT_BOR:
578 return "|";
579 case MemoryAccess::RT_BXOR:
580 return "^";
581 case MemoryAccess::RT_BAND:
582 return "&";
583 }
584 llvm_unreachable("Unknown reduction type");
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000585}
586
Michael Kruse2fa35192016-09-01 19:53:31 +0000587const ScopArrayInfo *MemoryAccess::getOriginalScopArrayInfo() const {
Tobias Grosser1959dbd2017-07-23 04:08:59 +0000588 isl::id ArrayId = getArrayId();
589 void *User = ArrayId.get_user();
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000590 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000591 return SAI;
592}
593
Michael Kruse2fa35192016-09-01 19:53:31 +0000594const ScopArrayInfo *MemoryAccess::getLatestScopArrayInfo() const {
Tobias Grosser1959dbd2017-07-23 04:08:59 +0000595 isl::id ArrayId = getLatestArrayId();
596 void *User = ArrayId.get_user();
Michael Kruse2fa35192016-09-01 19:53:31 +0000597 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
Michael Kruse2fa35192016-09-01 19:53:31 +0000598 return SAI;
599}
600
Tobias Grosser1959dbd2017-07-23 04:08:59 +0000601isl::id MemoryAccess::getOriginalArrayId() const {
602 return AccessRelation.get_tuple_id(isl::dim::out);
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000603}
604
Tobias Grosser1959dbd2017-07-23 04:08:59 +0000605isl::id MemoryAccess::getLatestArrayId() const {
Michael Kruse2fa35192016-09-01 19:53:31 +0000606 if (!hasNewAccessRelation())
607 return getOriginalArrayId();
Tobias Grosser1959dbd2017-07-23 04:08:59 +0000608 return NewAccessRelation.get_tuple_id(isl::dim::out);
Michael Kruse2fa35192016-09-01 19:53:31 +0000609}
610
Tobias Grosser6a870362017-07-23 04:08:45 +0000611isl::map MemoryAccess::getAddressFunction() const {
612 return getAccessRelation().lexmin();
Tobias Grosserd840fc72016-02-04 13:18:42 +0000613}
614
Tobias Grosser3b196132017-07-23 04:08:52 +0000615isl::pw_multi_aff
616MemoryAccess::applyScheduleToAccessRelation(isl::union_map USchedule) const {
617 isl::map Schedule, ScheduledAccRel;
618 isl::union_set UDomain;
Johannes Doerferta99130f2014-10-13 12:58:03 +0000619
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000620 UDomain = getStatement()->getDomain();
Tobias Grosser3b196132017-07-23 04:08:52 +0000621 USchedule = USchedule.intersect_domain(UDomain);
622 Schedule = isl::map::from_union_map(USchedule);
623 ScheduledAccRel = getAddressFunction().apply_domain(Schedule);
624 return isl::pw_multi_aff::from_map(ScheduledAccRel);
Johannes Doerferta99130f2014-10-13 12:58:03 +0000625}
626
Tobias Grosser22da5f02017-07-23 04:08:27 +0000627isl::map MemoryAccess::getOriginalAccessRelation() const {
628 return AccessRelation;
Tobias Grosser5d453812011-10-06 00:04:11 +0000629}
630
Johannes Doerferta99130f2014-10-13 12:58:03 +0000631std::string MemoryAccess::getOriginalAccessRelationStr() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +0000632 return AccessRelation.to_str();
Tobias Grosser5d453812011-10-06 00:04:11 +0000633}
634
Tobias Grosser22da5f02017-07-23 04:08:27 +0000635isl::space MemoryAccess::getOriginalAccessRelationSpace() const {
636 return AccessRelation.get_space();
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000637}
638
Tobias Grosser1515f6b2017-07-23 04:08:38 +0000639isl::map MemoryAccess::getNewAccessRelation() const {
640 return NewAccessRelation;
Tobias Grosser75805372011-04-29 06:27:02 +0000641}
642
Tobias Grosser6f730082015-09-05 07:46:47 +0000643std::string MemoryAccess::getNewAccessRelationStr() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +0000644 return NewAccessRelation.to_str();
Tobias Grosser6f730082015-09-05 07:46:47 +0000645}
646
Tobias Grosser6a4c12f2017-07-11 10:10:13 +0000647std::string MemoryAccess::getAccessRelationStr() const {
Tobias Grosser2b7479b2017-08-06 11:41:10 +0000648 return getAccessRelation().to_str();
Tobias Grosser6a4c12f2017-07-11 10:10:13 +0000649}
650
Tobias Grosserb6e7a852017-07-23 04:08:17 +0000651isl::basic_map MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
652 isl::space Space = isl::space(Statement->getIslCtx(), 0, 1);
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000653 Space = Space.align_params(Statement->getDomainSpace());
Tobias Grosser75805372011-04-29 06:27:02 +0000654
Tobias Grosserb6e7a852017-07-23 04:08:17 +0000655 return isl::basic_map::from_domain_and_range(
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000656 isl::basic_set::universe(Statement->getDomainSpace()),
Tobias Grosserb6e7a852017-07-23 04:08:17 +0000657 isl::basic_set::universe(Space));
Tobias Grosser75805372011-04-29 06:27:02 +0000658}
659
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000660// Formalize no out-of-bound access assumption
661//
662// When delinearizing array accesses we optimistically assume that the
663// delinearized accesses do not access out of bound locations (the subscript
664// expression of each array evaluates for each statement instance that is
665// executed to a value that is larger than zero and strictly smaller than the
666// size of the corresponding dimension). The only exception is the outermost
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000667// dimension for which we do not need to assume any upper bound. At this point
668// we formalize this assumption to ensure that at code generation time the
669// relevant run-time checks can be generated.
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000670//
671// To find the set of constraints necessary to avoid out of bound accesses, we
672// first build the set of data locations that are not within array bounds. We
673// then apply the reverse access relation to obtain the set of iterations that
674// may contain invalid accesses and reduce this set of iterations to the ones
675// that are actually executed by intersecting them with the domain of the
676// statement. If we now project out all loop dimensions, we obtain a set of
677// parameters that may cause statement instances to be executed that may
678// possibly yield out of bound memory accesses. The complement of these
679// constraints is the set of constraints that needs to be assumed to ensure such
680// statement instances are never executed.
Michael Krusee2bccbb2015-09-18 19:59:43 +0000681void MemoryAccess::assumeNoOutOfBound() {
Tobias Grosser8a6e6052017-03-17 12:26:58 +0000682 if (PollyIgnoreInbounds)
683 return;
Johannes Doerfertadeab372016-02-07 13:57:32 +0000684 auto *SAI = getScopArrayInfo();
Tobias Grosser22da5f02017-07-23 04:08:27 +0000685 isl::space Space = getOriginalAccessRelationSpace().range();
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000686 isl::set Outside = isl::set::empty(Space);
687 for (int i = 1, Size = Space.dim(isl::dim::set); i < Size; ++i) {
688 isl::local_space LS(Space);
689 isl::pw_aff Var = isl::pw_aff::var_on_domain(LS, isl::dim::set, i);
690 isl::pw_aff Zero = isl::pw_aff(LS);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000691
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000692 isl::set DimOutside = Var.lt_set(Zero);
Tobias Grosser77eef902017-07-21 23:07:56 +0000693 isl::pw_aff SizeE = SAI->getDimensionSizePw(i);
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000694 SizeE = SizeE.add_dims(isl::dim::in, Space.dim(isl::dim::set));
695 SizeE = SizeE.set_tuple_id(isl::dim::in, Space.get_tuple_id(isl::dim::set));
696 DimOutside = DimOutside.unite(SizeE.le_set(Var));
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000697
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000698 Outside = Outside.unite(DimOutside);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000699 }
700
Tobias Grosser1515f6b2017-07-23 04:08:38 +0000701 Outside = Outside.apply(getAccessRelation().reverse());
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000702 Outside = Outside.intersect(Statement->getDomain());
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000703 Outside = Outside.params();
Tobias Grosserf54bb772015-06-26 12:09:28 +0000704
705 // Remove divs to avoid the construction of overly complicated assumptions.
706 // Doing so increases the set of parameter combinations that are assumed to
707 // not appear. This is always save, but may make the resulting run-time check
708 // bail out more often than strictly necessary.
Tobias Grosser1e2edaf2017-05-23 07:07:07 +0000709 Outside = Outside.remove_divs();
710 Outside = Outside.complement();
Michael Kruse7071e8b2016-04-11 13:24:29 +0000711 const auto &Loc = getAccessInstruction()
712 ? getAccessInstruction()->getDebugLoc()
713 : DebugLoc();
Tobias Grosserd7c49752017-02-28 09:45:54 +0000714 if (!PollyPreciseInbounds)
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000715 Outside = Outside.gist_params(Statement->getDomain().params());
Philip Pfaffe00fd43b2017-11-19 22:13:34 +0000716 Statement->getParent()->recordAssumption(INBOUNDS, Outside, Loc,
Johannes Doerfert3bf6e4122016-04-12 13:27:35 +0000717 AS_ASSUMPTION);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000718}
719
Johannes Doerfertcea61932016-02-21 19:13:19 +0000720void MemoryAccess::buildMemIntrinsicAccessRelation() {
Johannes Doerfertc9765462016-11-17 22:11:56 +0000721 assert(isMemoryIntrinsic());
Roman Gareevf5aff702016-09-12 17:08:31 +0000722 assert(Subscripts.size() == 2 && Sizes.size() == 1);
Johannes Doerfertcea61932016-02-21 19:13:19 +0000723
Tobias Grossercdf471b2017-07-24 16:36:34 +0000724 isl::pw_aff SubscriptPWA = getPwAff(Subscripts[0]);
Tobias Grosser53fc3552017-05-23 07:07:09 +0000725 isl::map SubscriptMap = isl::map::from_pw_aff(SubscriptPWA);
Johannes Doerferta7920982016-02-25 14:08:48 +0000726
Tobias Grosser53fc3552017-05-23 07:07:09 +0000727 isl::map LengthMap;
Johannes Doerferta7920982016-02-25 14:08:48 +0000728 if (Subscripts[1] == nullptr) {
Tobias Grosser53fc3552017-05-23 07:07:09 +0000729 LengthMap = isl::map::universe(SubscriptMap.get_space());
Johannes Doerferta7920982016-02-25 14:08:48 +0000730 } else {
Tobias Grossercdf471b2017-07-24 16:36:34 +0000731 isl::pw_aff LengthPWA = getPwAff(Subscripts[1]);
Tobias Grosser53fc3552017-05-23 07:07:09 +0000732 LengthMap = isl::map::from_pw_aff(LengthPWA);
733 isl::space RangeSpace = LengthMap.get_space().range();
734 LengthMap = LengthMap.apply_range(isl::map::lex_gt(RangeSpace));
Johannes Doerferta7920982016-02-25 14:08:48 +0000735 }
Tobias Grosser53fc3552017-05-23 07:07:09 +0000736 LengthMap = LengthMap.lower_bound_si(isl::dim::out, 0, 0);
737 LengthMap = LengthMap.align_params(SubscriptMap.get_space());
738 SubscriptMap = SubscriptMap.align_params(LengthMap.get_space());
739 LengthMap = LengthMap.sum(SubscriptMap);
740 AccessRelation =
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000741 LengthMap.set_tuple_id(isl::dim::in, getStatement()->getDomainId());
Johannes Doerfertcea61932016-02-21 19:13:19 +0000742}
743
Johannes Doerferte7044942015-02-24 11:58:30 +0000744void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) {
745 ScalarEvolution *SE = Statement->getParent()->getSE();
746
Johannes Doerfertcea61932016-02-21 19:13:19 +0000747 auto MAI = MemAccInst(getAccessInstruction());
Hongbin Zheng8efb22e2016-02-27 01:49:58 +0000748 if (isa<MemIntrinsic>(MAI))
Johannes Doerfertcea61932016-02-21 19:13:19 +0000749 return;
750
751 Value *Ptr = MAI.getPointerOperand();
Johannes Doerferte7044942015-02-24 11:58:30 +0000752 if (!Ptr || !SE->isSCEVable(Ptr->getType()))
753 return;
754
755 auto *PtrSCEV = SE->getSCEV(Ptr);
756 if (isa<SCEVCouldNotCompute>(PtrSCEV))
757 return;
758
759 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
760 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
761 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
762
763 const ConstantRange &Range = SE->getSignedRange(PtrSCEV);
764 if (Range.isFullSet())
765 return;
766
Nikita Popov6d855ea2019-03-27 18:19:33 +0000767 if (Range.isUpperWrapped() || Range.isSignWrappedSet())
Tobias Grosserb3a85882017-02-12 08:11:12 +0000768 return;
769
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000770 bool isWrapping = Range.isSignWrappedSet();
Tobias Grosserb3a85882017-02-12 08:11:12 +0000771
Johannes Doerferte7044942015-02-24 11:58:30 +0000772 unsigned BW = Range.getBitWidth();
Johannes Doerferte7087902016-02-07 13:59:03 +0000773 const auto One = APInt(BW, 1);
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000774 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin();
Johannes Doerferte7087902016-02-07 13:59:03 +0000775 const auto UB = isWrapping ? (Range.getUpper() - One) : Range.getSignedMax();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000776
777 auto Min = LB.sdiv(APInt(BW, ElementSize));
Johannes Doerferte7087902016-02-07 13:59:03 +0000778 auto Max = UB.sdiv(APInt(BW, ElementSize)) + One;
Johannes Doerferte7044942015-02-24 11:58:30 +0000779
Tobias Grosserb3a85882017-02-12 08:11:12 +0000780 assert(Min.sle(Max) && "Minimum expected to be less or equal than max");
781
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000782 isl::map Relation = AccessRelation;
Tobias Grosser99ea1d02017-05-21 20:23:20 +0000783 isl::set AccessRange = Relation.range();
784 AccessRange = addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0,
785 isl::dim::set);
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000786 AccessRelation = Relation.intersect_range(AccessRange);
Johannes Doerferte7044942015-02-24 11:58:30 +0000787}
788
Tobias Grosser491b7992016-12-02 05:21:22 +0000789void MemoryAccess::foldAccessRelation() {
790 if (Sizes.size() < 2 || isa<SCEVConstant>(Sizes[1]))
791 return;
792
Michael Krusee2bccbb2015-09-18 19:59:43 +0000793 int Size = Subscripts.size();
Tobias Grosser619190d2015-03-30 17:22:28 +0000794
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000795 isl::map NewAccessRelation = AccessRelation;
Tobias Grosserc2f15102017-03-01 21:11:27 +0000796
Tobias Grosser619190d2015-03-30 17:22:28 +0000797 for (int i = Size - 2; i >= 0; --i) {
Tobias Grossera32de132017-05-23 07:22:56 +0000798 isl::space Space;
799 isl::map MapOne, MapTwo;
Tobias Grossercdf471b2017-07-24 16:36:34 +0000800 isl::pw_aff DimSize = getPwAff(Sizes[i + 1]);
Tobias Grosser619190d2015-03-30 17:22:28 +0000801
Tobias Grossera32de132017-05-23 07:22:56 +0000802 isl::space SpaceSize = DimSize.get_space();
Tobias Grosserd3d3d6b2018-04-29 00:28:26 +0000803 isl::id ParamId = SpaceSize.get_dim_id(isl::dim::param, 0);
Tobias Grosser619190d2015-03-30 17:22:28 +0000804
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000805 Space = AccessRelation.get_space();
Tobias Grossera32de132017-05-23 07:22:56 +0000806 Space = Space.range().map_from_set();
807 Space = Space.align_params(SpaceSize);
Tobias Grosser619190d2015-03-30 17:22:28 +0000808
Tobias Grossera32de132017-05-23 07:22:56 +0000809 int ParamLocation = Space.find_dim_by_id(isl::dim::param, ParamId);
Tobias Grosser619190d2015-03-30 17:22:28 +0000810
Tobias Grossera32de132017-05-23 07:22:56 +0000811 MapOne = isl::map::universe(Space);
Tobias Grosser619190d2015-03-30 17:22:28 +0000812 for (int j = 0; j < Size; ++j)
Tobias Grossera32de132017-05-23 07:22:56 +0000813 MapOne = MapOne.equate(isl::dim::in, j, isl::dim::out, j);
814 MapOne = MapOne.lower_bound_si(isl::dim::in, i + 1, 0);
Tobias Grosser619190d2015-03-30 17:22:28 +0000815
Tobias Grossera32de132017-05-23 07:22:56 +0000816 MapTwo = isl::map::universe(Space);
Tobias Grosser619190d2015-03-30 17:22:28 +0000817 for (int j = 0; j < Size; ++j)
818 if (j < i || j > i + 1)
Tobias Grossera32de132017-05-23 07:22:56 +0000819 MapTwo = MapTwo.equate(isl::dim::in, j, isl::dim::out, j);
Tobias Grosser619190d2015-03-30 17:22:28 +0000820
Tobias Grossera32de132017-05-23 07:22:56 +0000821 isl::local_space LS(Space);
822 isl::constraint C;
823 C = isl::constraint::alloc_equality(LS);
824 C = C.set_constant_si(-1);
825 C = C.set_coefficient_si(isl::dim::in, i, 1);
826 C = C.set_coefficient_si(isl::dim::out, i, -1);
827 MapTwo = MapTwo.add_constraint(C);
828 C = isl::constraint::alloc_equality(LS);
829 C = C.set_coefficient_si(isl::dim::in, i + 1, 1);
830 C = C.set_coefficient_si(isl::dim::out, i + 1, -1);
831 C = C.set_coefficient_si(isl::dim::param, ParamLocation, 1);
832 MapTwo = MapTwo.add_constraint(C);
833 MapTwo = MapTwo.upper_bound_si(isl::dim::in, i + 1, -1);
Tobias Grosser619190d2015-03-30 17:22:28 +0000834
Tobias Grossera32de132017-05-23 07:22:56 +0000835 MapOne = MapOne.unite(MapTwo);
836 NewAccessRelation = NewAccessRelation.apply_range(MapOne);
Tobias Grosser619190d2015-03-30 17:22:28 +0000837 }
Tobias Grosser491b7992016-12-02 05:21:22 +0000838
Tobias Grosser77eef902017-07-21 23:07:56 +0000839 isl::id BaseAddrId = getScopArrayInfo()->getBasePtrId();
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000840 isl::space Space = Statement->getDomainSpace();
Tobias Grossera32de132017-05-23 07:22:56 +0000841 NewAccessRelation = NewAccessRelation.set_tuple_id(
842 isl::dim::in, Space.get_tuple_id(isl::dim::set));
843 NewAccessRelation = NewAccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000844 NewAccessRelation = NewAccessRelation.gist_domain(Statement->getDomain());
Tobias Grosserc2f15102017-03-01 21:11:27 +0000845
846 // Access dimension folding might in certain cases increase the number of
847 // disjuncts in the memory access, which can possibly complicate the generated
848 // run-time checks and can lead to costly compilation.
Tobias Grossera32de132017-05-23 07:22:56 +0000849 if (!PollyPreciseFoldAccesses &&
Tobias Grosser6ec6e1d2018-06-19 08:13:53 +0000850 NewAccessRelation.n_basic_map() > AccessRelation.n_basic_map()) {
Tobias Grosserc2f15102017-03-01 21:11:27 +0000851 } else {
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000852 AccessRelation = NewAccessRelation;
Tobias Grosserc2f15102017-03-01 21:11:27 +0000853 }
Tobias Grosser619190d2015-03-30 17:22:28 +0000854}
855
Tobias Grosserc80d6972016-09-02 06:33:33 +0000856/// Check if @p Expr is divisible by @p Size.
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000857static bool isDivisible(const SCEV *Expr, unsigned Size, ScalarEvolution &SE) {
Johannes Doerferta7920982016-02-25 14:08:48 +0000858 assert(Size != 0);
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +0000859 if (Size == 1)
860 return true;
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000861
862 // Only one factor needs to be divisible.
863 if (auto *MulExpr = dyn_cast<SCEVMulExpr>(Expr)) {
864 for (auto *FactorExpr : MulExpr->operands())
865 if (isDivisible(FactorExpr, Size, SE))
866 return true;
867 return false;
868 }
869
870 // For other n-ary expressions (Add, AddRec, Max,...) all operands need
Michael Krusea6d48f52017-06-08 12:06:15 +0000871 // to be divisible.
Johannes Doerferta4b77c02015-11-12 20:15:32 +0000872 if (auto *NAryExpr = dyn_cast<SCEVNAryExpr>(Expr)) {
873 for (auto *OpExpr : NAryExpr->operands())
874 if (!isDivisible(OpExpr, Size, SE))
875 return false;
876 return true;
877 }
878
879 auto *SizeSCEV = SE.getConstant(Expr->getType(), Size);
880 auto *UDivSCEV = SE.getUDivExpr(Expr, SizeSCEV);
881 auto *MulSCEV = SE.getMulExpr(UDivSCEV, SizeSCEV);
882 return MulSCEV == Expr;
883}
884
Michael Krusee2bccbb2015-09-18 19:59:43 +0000885void MemoryAccess::buildAccessRelation(const ScopArrayInfo *SAI) {
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000886 assert(AccessRelation.is_null() && "AccessRelation already built");
Tobias Grosser75805372011-04-29 06:27:02 +0000887
Johannes Doerfert85676e32016-04-23 14:32:34 +0000888 // Initialize the invalid domain which describes all iterations for which the
889 // access relation is not modeled correctly.
Tobias Grosser2332fa32017-08-06 15:36:48 +0000890 isl::set StmtInvalidDomain = getStatement()->getInvalidDomain();
Tobias Grosserb739cb42017-07-24 20:30:34 +0000891 InvalidDomain = isl::set::empty(StmtInvalidDomain.get_space());
Johannes Doerfert85676e32016-04-23 14:32:34 +0000892
Tobias Grosserb739cb42017-07-24 20:30:34 +0000893 isl::ctx Ctx = Id.get_ctx();
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000894 isl::id BaseAddrId = SAI->getBasePtrId();
Tobias Grosser5683df42011-11-09 22:34:34 +0000895
Eli Friedmanb9c6f012016-11-01 20:53:11 +0000896 if (getAccessInstruction() && isa<MemIntrinsic>(getAccessInstruction())) {
897 buildMemIntrinsicAccessRelation();
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000898 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
Eli Friedmanb9c6f012016-11-01 20:53:11 +0000899 return;
900 }
Johannes Doerfertcea61932016-02-21 19:13:19 +0000901
Eli Friedmanb9c6f012016-11-01 20:53:11 +0000902 if (!isAffine()) {
Tobias Grosser4f967492013-06-23 05:21:18 +0000903 // We overapproximate non-affine accesses with a possible access to the
904 // whole array. For read accesses it does not make a difference, if an
905 // access must or may happen. However, for write accesses it is important to
906 // differentiate between writes that must happen and writes that may happen.
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000907 if (AccessRelation.is_null())
908 AccessRelation = createBasicAccessMap(Statement);
Johannes Doerfertcea61932016-02-21 19:13:19 +0000909
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000910 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
Tobias Grossera1879642011-12-20 10:43:14 +0000911 return;
912 }
913
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000914 isl::space Space = isl::space(Ctx, 0, Statement->getNumIterators(), 0);
915 AccessRelation = isl::map::universe(Space);
Tobias Grossera1879642011-12-20 10:43:14 +0000916
Michael Krusee2bccbb2015-09-18 19:59:43 +0000917 for (int i = 0, Size = Subscripts.size(); i < Size; ++i) {
Tobias Grossercdf471b2017-07-24 16:36:34 +0000918 isl::pw_aff Affine = getPwAff(Subscripts[i]);
919 isl::map SubscriptMap = isl::map::from_pw_aff(Affine);
920 AccessRelation = AccessRelation.flat_range_product(SubscriptMap);
Sebastian Pop18016682014-04-08 21:20:44 +0000921 }
922
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000923 Space = Statement->getDomainSpace();
Tobias Grosser0c4c2ee2017-07-23 04:08:22 +0000924 AccessRelation = AccessRelation.set_tuple_id(
925 isl::dim::in, Space.get_tuple_id(isl::dim::set));
926 AccessRelation = AccessRelation.set_tuple_id(isl::dim::out, BaseAddrId);
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000927
Tobias Grosserdcf8d692017-08-06 16:39:52 +0000928 AccessRelation = AccessRelation.gist_domain(Statement->getDomain());
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000929}
Tobias Grosser30b8a092011-08-18 07:51:37 +0000930
Michael Krusecac948e2015-10-02 13:53:07 +0000931MemoryAccess::MemoryAccess(ScopStmt *Stmt, Instruction *AccessInst,
Johannes Doerfertcea61932016-02-21 19:13:19 +0000932 AccessType AccType, Value *BaseAddress,
933 Type *ElementType, bool Affine,
Michael Krusee2bccbb2015-09-18 19:59:43 +0000934 ArrayRef<const SCEV *> Subscripts,
935 ArrayRef<const SCEV *> Sizes, Value *AccessValue,
Tobias Grosser72684bb2017-05-03 08:02:32 +0000936 MemoryKind Kind)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000937 : Kind(Kind), AccType(AccType), Statement(Stmt), InvalidDomain(nullptr),
938 BaseAddr(BaseAddress), ElementType(ElementType),
Tobias Grosser81331282017-05-03 07:57:35 +0000939 Sizes(Sizes.begin(), Sizes.end()), AccessInstruction(AccessInst),
940 AccessValue(AccessValue), IsAffine(Affine),
Michael Krusee2bccbb2015-09-18 19:59:43 +0000941 Subscripts(Subscripts.begin(), Subscripts.end()), AccessRelation(nullptr),
Siddharth Bhatf2dbba82017-05-10 13:11:20 +0000942 NewAccessRelation(nullptr), FAD(nullptr) {
Hongbin Zheng86f43ea2016-02-20 03:40:15 +0000943 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
Tobias Grosser81331282017-05-03 07:57:35 +0000944 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size());
Tobias Grosserf1bfd752015-11-05 20:15:37 +0000945
Tobias Grosser81331282017-05-03 07:57:35 +0000946 std::string IdName = Stmt->getBaseName() + Access;
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000947 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this);
Tobias Grosserf1bfd752015-11-05 20:15:37 +0000948}
Michael Krusee2bccbb2015-09-18 19:59:43 +0000949
Tobias Grosser1f6ba7e2017-07-24 16:22:32 +0000950MemoryAccess::MemoryAccess(ScopStmt *Stmt, AccessType AccType, isl::map AccRel)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000951 : Kind(MemoryKind::Array), AccType(AccType), Statement(Stmt),
952 InvalidDomain(nullptr), AccessRelation(nullptr),
953 NewAccessRelation(AccRel), FAD(nullptr) {
Tobias Grosser206e9e32017-07-24 16:22:27 +0000954 isl::id ArrayInfoId = NewAccessRelation.get_tuple_id(isl::dim::out);
Roman Gareevb3224ad2016-09-14 06:26:09 +0000955 auto *SAI = ScopArrayInfo::getFromId(ArrayInfoId);
956 Sizes.push_back(nullptr);
957 for (unsigned i = 1; i < SAI->getNumberOfDimensions(); i++)
958 Sizes.push_back(SAI->getDimensionSize(i));
959 ElementType = SAI->getElementType();
960 BaseAddr = SAI->getBasePtr();
Roman Gareevb3224ad2016-09-14 06:26:09 +0000961 static const std::string TypeStrings[] = {"", "_Read", "_Write", "_MayWrite"};
Tobias Grosser81331282017-05-03 07:57:35 +0000962 const std::string Access = TypeStrings[AccType] + utostr(Stmt->size());
Roman Gareevb3224ad2016-09-14 06:26:09 +0000963
Tobias Grosser81331282017-05-03 07:57:35 +0000964 std::string IdName = Stmt->getBaseName() + Access;
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000965 Id = isl::id::alloc(Stmt->getParent()->getIslCtx(), IdName, this);
Roman Gareevb3224ad2016-09-14 06:26:09 +0000966}
967
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +0000968MemoryAccess::~MemoryAccess() = default;
969
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000970void MemoryAccess::realignParams() {
Tobias Grosser8ea1fc12017-08-06 19:52:38 +0000971 isl::set Ctx = Statement->getParent()->getContext();
Tobias Grosserb739cb42017-07-24 20:30:34 +0000972 InvalidDomain = InvalidDomain.gist_params(Ctx);
973 AccessRelation = AccessRelation.gist_params(Ctx);
Tobias Grosser75805372011-04-29 06:27:02 +0000974}
975
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000976const std::string MemoryAccess::getReductionOperatorStr() const {
977 return MemoryAccess::getReductionOperatorStr(getReductionType());
978}
979
Tobias Grosserfe46c3f2017-07-23 04:08:11 +0000980isl::id MemoryAccess::getId() const { return Id; }
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000981
Johannes Doerfertf6183392014-07-01 20:52:51 +0000982raw_ostream &polly::operator<<(raw_ostream &OS,
983 MemoryAccess::ReductionType RT) {
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000984 if (RT == MemoryAccess::RT_NONE)
Johannes Doerfertf6183392014-07-01 20:52:51 +0000985 OS << "NONE";
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000986 else
987 OS << MemoryAccess::getReductionOperatorStr(RT);
Johannes Doerfertf6183392014-07-01 20:52:51 +0000988 return OS;
989}
990
Siddharth Bhat0fe72312017-05-15 08:41:30 +0000991void MemoryAccess::setFortranArrayDescriptor(Value *FAD) { this->FAD = FAD; }
Siddharth Bhatf2dbba82017-05-10 13:11:20 +0000992
Tobias Grosser75805372011-04-29 06:27:02 +0000993void MemoryAccess::print(raw_ostream &OS) const {
Johannes Doerfert4c7ce472014-10-08 10:11:33 +0000994 switch (AccType) {
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000995 case READ:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000996 OS.indent(12) << "ReadAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000997 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000998 case MUST_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000999 OS.indent(12) << "MustWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +00001000 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +00001001 case MAY_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +00001002 OS.indent(12) << "MayWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +00001003 break;
1004 }
Siddharth Bhatf2dbba82017-05-10 13:11:20 +00001005
Johannes Doerfert0ff23ec2015-02-06 20:13:15 +00001006 OS << "[Reduction Type: " << getReductionType() << "] ";
Siddharth Bhatf2dbba82017-05-10 13:11:20 +00001007
1008 if (FAD) {
1009 OS << "[Fortran array descriptor: " << FAD->getName();
1010 OS << "] ";
1011 };
1012
Tobias Grossera535dff2015-12-13 19:59:01 +00001013 OS << "[Scalar: " << isScalarKind() << "]\n";
Michael Kruseb8d26442015-12-13 19:35:26 +00001014 OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
Tobias Grosser6f730082015-09-05 07:46:47 +00001015 if (hasNewAccessRelation())
1016 OS.indent(11) << "new: " << getNewAccessRelationStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001017}
1018
Michael Kruse5d518462017-07-21 15:54:07 +00001019#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Michael Krusee1860132017-07-21 15:54:13 +00001020LLVM_DUMP_METHOD void MemoryAccess::dump() const { print(errs()); }
Michael Kruse5d518462017-07-21 15:54:07 +00001021#endif
Tobias Grosser75805372011-04-29 06:27:02 +00001022
Tobias Grossercdf471b2017-07-24 16:36:34 +00001023isl::pw_aff MemoryAccess::getPwAff(const SCEV *E) {
Johannes Doerfert97f0dcd2016-04-12 13:26:45 +00001024 auto *Stmt = getStatement();
Johannes Doerfert85676e32016-04-23 14:32:34 +00001025 PWACtx PWAC = Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock());
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001026 isl::set StmtDom = getStatement()->getDomain();
Tobias Grossercdf471b2017-07-24 16:36:34 +00001027 StmtDom = StmtDom.reset_tuple_id();
Philip Pfaffed98dbee2017-12-06 21:02:22 +00001028 isl::set NewInvalidDom = StmtDom.intersect(PWAC.second);
Tobias Grosserb739cb42017-07-24 20:30:34 +00001029 InvalidDomain = InvalidDomain.unite(NewInvalidDom);
Philip Pfaffed98dbee2017-12-06 21:02:22 +00001030 return PWAC.first;
Johannes Doerfert97f0dcd2016-04-12 13:26:45 +00001031}
1032
Tobias Grosser75805372011-04-29 06:27:02 +00001033// Create a map in the size of the provided set domain, that maps from the
1034// one element of the provided set domain to another element of the provided
1035// set domain.
1036// The mapping is limited to all points that are equal in all but the last
1037// dimension and for which the last dimension of the input is strict smaller
1038// than the last dimension of the output.
1039//
1040// getEqualAndLarger(set[i0, i1, ..., iX]):
1041//
1042// set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
1043// : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
1044//
Tobias Grosserd7065e52017-07-24 20:50:22 +00001045static isl::map getEqualAndLarger(isl::space SetDomain) {
1046 isl::space Space = SetDomain.map_from_set();
1047 isl::map Map = isl::map::universe(Space);
1048 unsigned lastDimension = Map.dim(isl::dim::in) - 1;
Tobias Grosser75805372011-04-29 06:27:02 +00001049
1050 // Set all but the last dimension to be equal for the input and output
1051 //
1052 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
1053 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
Sebastian Pop40408762013-10-04 17:14:53 +00001054 for (unsigned i = 0; i < lastDimension; ++i)
Tobias Grosserd7065e52017-07-24 20:50:22 +00001055 Map = Map.equate(isl::dim::in, i, isl::dim::out, i);
Tobias Grosser75805372011-04-29 06:27:02 +00001056
1057 // Set the last dimension of the input to be strict smaller than the
1058 // last dimension of the output.
1059 //
1060 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
Tobias Grosserd7065e52017-07-24 20:50:22 +00001061 Map = Map.order_lt(isl::dim::in, lastDimension, isl::dim::out, lastDimension);
Tobias Grosserc327932c2012-02-01 14:23:36 +00001062 return Map;
Tobias Grosser75805372011-04-29 06:27:02 +00001063}
1064
Tobias Grosserd7065e52017-07-24 20:50:22 +00001065isl::set MemoryAccess::getStride(isl::map Schedule) const {
1066 isl::map AccessRelation = getAccessRelation();
1067 isl::space Space = Schedule.get_space().range();
1068 isl::map NextScatt = getEqualAndLarger(Space);
Tobias Grosser75805372011-04-29 06:27:02 +00001069
Tobias Grosserd7065e52017-07-24 20:50:22 +00001070 Schedule = Schedule.reverse();
1071 NextScatt = NextScatt.lexmin();
Tobias Grosser75805372011-04-29 06:27:02 +00001072
Tobias Grosserd7065e52017-07-24 20:50:22 +00001073 NextScatt = NextScatt.apply_range(Schedule);
1074 NextScatt = NextScatt.apply_range(AccessRelation);
1075 NextScatt = NextScatt.apply_domain(Schedule);
1076 NextScatt = NextScatt.apply_domain(AccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +00001077
Tobias Grosserd7065e52017-07-24 20:50:22 +00001078 isl::set Deltas = NextScatt.deltas();
Sebastian Popa00a0292012-12-18 07:46:06 +00001079 return Deltas;
Tobias Grosser75805372011-04-29 06:27:02 +00001080}
1081
Tobias Grosserd7065e52017-07-24 20:50:22 +00001082bool MemoryAccess::isStrideX(isl::map Schedule, int StrideWidth) const {
1083 isl::set Stride, StrideX;
Tobias Grosser28dd4862012-01-24 16:42:16 +00001084 bool IsStrideX;
Tobias Grosser75805372011-04-29 06:27:02 +00001085
Sebastian Popa00a0292012-12-18 07:46:06 +00001086 Stride = getStride(Schedule);
Tobias Grosserd7065e52017-07-24 20:50:22 +00001087 StrideX = isl::set::universe(Stride.get_space());
1088 for (unsigned i = 0; i < StrideX.dim(isl::dim::set) - 1; i++)
1089 StrideX = StrideX.fix_si(isl::dim::set, i, 0);
1090 StrideX = StrideX.fix_si(isl::dim::set, StrideX.dim(isl::dim::set) - 1,
1091 StrideWidth);
1092 IsStrideX = Stride.is_subset(StrideX);
Tobias Grosserb76f38532011-08-20 11:11:25 +00001093
Tobias Grosser28dd4862012-01-24 16:42:16 +00001094 return IsStrideX;
1095}
1096
Tobias Grosserd7065e52017-07-24 20:50:22 +00001097bool MemoryAccess::isStrideZero(isl::map Schedule) const {
Sebastian Popa00a0292012-12-18 07:46:06 +00001098 return isStrideX(Schedule, 0);
Tobias Grosser75805372011-04-29 06:27:02 +00001099}
1100
Tobias Grosserd7065e52017-07-24 20:50:22 +00001101bool MemoryAccess::isStrideOne(isl::map Schedule) const {
Sebastian Popa00a0292012-12-18 07:46:06 +00001102 return isStrideX(Schedule, 1);
Tobias Grosser75805372011-04-29 06:27:02 +00001103}
1104
Tobias Grosser6d588042017-08-02 19:27:16 +00001105void MemoryAccess::setAccessRelation(isl::map NewAccess) {
1106 AccessRelation = NewAccess;
Tobias Grosserbedef002016-12-02 08:10:56 +00001107}
1108
Tobias Grosser7b45af12017-08-02 19:27:25 +00001109void MemoryAccess::setNewAccessRelation(isl::map NewAccess) {
Michael Kruse772ce722016-09-01 19:16:58 +00001110 assert(NewAccess);
1111
1112#ifndef NDEBUG
1113 // Check domain space compatibility.
Tobias Grosser7b45af12017-08-02 19:27:25 +00001114 isl::space NewSpace = NewAccess.get_space();
1115 isl::space NewDomainSpace = NewSpace.domain();
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001116 isl::space OriginalDomainSpace = getStatement()->getDomainSpace();
Tobias Grosser7b45af12017-08-02 19:27:25 +00001117 assert(OriginalDomainSpace.has_equal_tuples(NewDomainSpace));
Michael Kruse772ce722016-09-01 19:16:58 +00001118
Michael Kruse706f79a2017-05-21 22:46:57 +00001119 // Reads must be executed unconditionally. Writes might be executed in a
1120 // subdomain only.
1121 if (isRead()) {
1122 // Check whether there is an access for every statement instance.
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001123 isl::set StmtDomain = getStatement()->getDomain();
Tobias Grosserb65ccc42017-08-06 20:11:59 +00001124 StmtDomain =
1125 StmtDomain.intersect_params(getStatement()->getParent()->getContext());
Tobias Grosser7b45af12017-08-02 19:27:25 +00001126 isl::set NewDomain = NewAccess.domain();
1127 assert(StmtDomain.is_subset(NewDomain) &&
Michael Kruse706f79a2017-05-21 22:46:57 +00001128 "Partial READ accesses not supported");
Michael Kruse706f79a2017-05-21 22:46:57 +00001129 }
Michael Kruse772ce722016-09-01 19:16:58 +00001130
Tobias Grosser7b45af12017-08-02 19:27:25 +00001131 isl::space NewAccessSpace = NewAccess.get_space();
1132 assert(NewAccessSpace.has_tuple_id(isl::dim::set) &&
Michael Kruse772ce722016-09-01 19:16:58 +00001133 "Must specify the array that is accessed");
Tobias Grosser7b45af12017-08-02 19:27:25 +00001134 isl::id NewArrayId = NewAccessSpace.get_tuple_id(isl::dim::set);
1135 auto *SAI = static_cast<ScopArrayInfo *>(NewArrayId.get_user());
Michael Kruse772ce722016-09-01 19:16:58 +00001136 assert(SAI && "Must set a ScopArrayInfo");
Tobias Grossere1ff0cf2017-01-17 12:00:42 +00001137
1138 if (SAI->isArrayKind() && SAI->getBasePtrOriginSAI()) {
1139 InvariantEquivClassTy *EqClass =
1140 getStatement()->getParent()->lookupInvariantEquivClass(
1141 SAI->getBasePtr());
1142 assert(EqClass &&
1143 "Access functions to indirect arrays must have an invariant and "
1144 "hoisted base pointer");
1145 }
1146
1147 // Check whether access dimensions correspond to number of dimensions of the
1148 // accesses array.
Michael Kruse772ce722016-09-01 19:16:58 +00001149 auto Dims = SAI->getNumberOfDimensions();
Tobias Grosser7b45af12017-08-02 19:27:25 +00001150 assert(NewAccessSpace.dim(isl::dim::set) == Dims &&
Michael Kruse772ce722016-09-01 19:16:58 +00001151 "Access dims must match array dims");
Michael Kruse772ce722016-09-01 19:16:58 +00001152#endif
1153
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001154 NewAccess = NewAccess.gist_domain(getStatement()->getDomain());
Tobias Grosser7b45af12017-08-02 19:27:25 +00001155 NewAccessRelation = NewAccess;
Raghesh Aloor3cb66282011-07-12 17:14:03 +00001156}
Tobias Grosser75805372011-04-29 06:27:02 +00001157
Michael Kruse706f79a2017-05-21 22:46:57 +00001158bool MemoryAccess::isLatestPartialAccess() const {
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001159 isl::set StmtDom = getStatement()->getDomain();
Tobias Grosser1515f6b2017-07-23 04:08:38 +00001160 isl::set AccDom = getLatestAccessRelation().domain();
Michael Kruse706f79a2017-05-21 22:46:57 +00001161
Tobias Grosserd3d3d6b2018-04-29 00:28:26 +00001162 return !StmtDom.is_subset(AccDom);
Michael Kruse706f79a2017-05-21 22:46:57 +00001163}
1164
Tobias Grosser75805372011-04-29 06:27:02 +00001165//===----------------------------------------------------------------------===//
Tobias Grossercf3942d2011-10-06 00:04:05 +00001166
Tobias Grosser6ad16402017-08-06 17:45:28 +00001167isl::map ScopStmt::getSchedule() const {
Tobias Grosser1e09c132017-08-14 06:49:06 +00001168 isl::set Domain = getDomain();
1169 if (Domain.is_empty())
1170 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace())));
1171 auto Schedule = getParent()->getSchedule();
1172 if (!Schedule)
Roman Gareevb3224ad2016-09-14 06:26:09 +00001173 return nullptr;
Tobias Grosser1e09c132017-08-14 06:49:06 +00001174 Schedule = Schedule.intersect_domain(isl::union_set(Domain));
1175 if (Schedule.is_empty())
1176 return isl::map::from_aff(isl::aff(isl::local_space(getDomainSpace())));
1177 isl::map M = M.from_union_map(Schedule);
1178 M = M.coalesce();
1179 M = M.gist_domain(Domain);
1180 M = M.coalesce();
1181 return M;
Tobias Grosser808cd692015-07-14 09:33:13 +00001182}
Tobias Grossercf3942d2011-10-06 00:04:05 +00001183
Tobias Grossera9b5bba2017-08-06 16:11:53 +00001184void ScopStmt::restrictDomain(isl::set NewDomain) {
1185 assert(NewDomain.is_subset(Domain) &&
Tobias Grosser37eb4222014-02-20 21:43:54 +00001186 "New domain is not a subset of old domain!");
Tobias Grosser37eb4222014-02-20 21:43:54 +00001187 Domain = NewDomain;
Tobias Grosser75805372011-04-29 06:27:02 +00001188}
1189
Michael Kruse70af4f52017-08-07 18:40:29 +00001190void ScopStmt::addAccess(MemoryAccess *Access, bool Prepend) {
Michael Krusecac948e2015-10-02 13:53:07 +00001191 Instruction *AccessInst = Access->getAccessInstruction();
1192
Michael Kruse58fa3bb2015-12-22 23:25:11 +00001193 if (Access->isArrayKind()) {
1194 MemoryAccessList &MAL = InstructionToAccess[AccessInst];
1195 MAL.emplace_front(Access);
Michael Kruse436db622016-01-26 13:33:10 +00001196 } else if (Access->isValueKind() && Access->isWrite()) {
1197 Instruction *AccessVal = cast<Instruction>(Access->getAccessValue());
Michael Kruse436db622016-01-26 13:33:10 +00001198 assert(!ValueWrites.lookup(AccessVal));
1199
1200 ValueWrites[AccessVal] = Access;
Michael Krusead28e5a2016-01-26 13:33:15 +00001201 } else if (Access->isValueKind() && Access->isRead()) {
1202 Value *AccessVal = Access->getAccessValue();
1203 assert(!ValueReads.lookup(AccessVal));
1204
1205 ValueReads[AccessVal] = Access;
Michael Kruseee6a4fc2016-01-26 13:33:27 +00001206 } else if (Access->isAnyPHIKind() && Access->isWrite()) {
Tobias Grosser5db171a2017-02-10 10:09:44 +00001207 PHINode *PHI = cast<PHINode>(Access->getAccessValue());
Michael Kruseee6a4fc2016-01-26 13:33:27 +00001208 assert(!PHIWrites.lookup(PHI));
1209
1210 PHIWrites[PHI] = Access;
Michael Kruse3562f272017-07-20 16:47:57 +00001211 } else if (Access->isAnyPHIKind() && Access->isRead()) {
1212 PHINode *PHI = cast<PHINode>(Access->getAccessValue());
1213 assert(!PHIReads.lookup(PHI));
1214
1215 PHIReads[PHI] = Access;
Michael Kruse58fa3bb2015-12-22 23:25:11 +00001216 }
1217
Michael Kruse70af4f52017-08-07 18:40:29 +00001218 if (Prepend) {
1219 MemAccs.insert(MemAccs.begin(), Access);
1220 return;
1221 }
Michael Kruse58fa3bb2015-12-22 23:25:11 +00001222 MemAccs.push_back(Access);
Michael Krusecac948e2015-10-02 13:53:07 +00001223}
1224
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001225void ScopStmt::realignParams() {
Johannes Doerfertf6752892014-06-13 18:01:45 +00001226 for (MemoryAccess *MA : *this)
1227 MA->realignParams();
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001228
Tobias Grosser8ea1fc12017-08-06 19:52:38 +00001229 isl::set Ctx = Parent.getContext();
Tobias Grosser2332fa32017-08-06 15:36:48 +00001230 InvalidDomain = InvalidDomain.gist_params(Ctx);
Tobias Grossera9b5bba2017-08-06 16:11:53 +00001231 Domain = Domain.gist_params(Ctx);
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001232}
1233
Tobias Grosser78a84942018-06-01 19:12:00 +00001234/// Add @p BSet to set @p BoundedParts if @p BSet is bounded.
1235static isl::set collectBoundedParts(isl::set S) {
1236 isl::set BoundedParts = isl::set::empty(S.get_space());
Tobias Grosser31e29a42018-07-16 19:04:16 +00001237 for (isl::basic_set BSet : S.get_basic_set_list())
1238 if (BSet.is_bounded())
Tobias Grosser78a84942018-06-01 19:12:00 +00001239 BoundedParts = BoundedParts.unite(isl::set(BSet));
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001240 return BoundedParts;
1241}
1242
Tobias Grosserc80d6972016-09-02 06:33:33 +00001243/// Compute the (un)bounded parts of @p S wrt. to dimension @p Dim.
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001244///
1245/// @returns A separation of @p S into first an unbounded then a bounded subset,
1246/// both with regards to the dimension @p Dim.
Tobias Grosser78a84942018-06-01 19:12:00 +00001247static std::pair<isl::set, isl::set> partitionSetParts(isl::set S,
1248 unsigned Dim) {
1249 for (unsigned u = 0, e = S.n_dim(); u < e; u++)
1250 S = S.lower_bound_si(isl::dim::set, u, 0);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001251
Tobias Grosser78a84942018-06-01 19:12:00 +00001252 unsigned NumDimsS = S.n_dim();
1253 isl::set OnlyDimS = S;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001254
1255 // Remove dimensions that are greater than Dim as they are not interesting.
1256 assert(NumDimsS >= Dim + 1);
Tobias Grosser78a84942018-06-01 19:12:00 +00001257 OnlyDimS = OnlyDimS.project_out(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001258
1259 // Create artificial parametric upper bounds for dimensions smaller than Dim
1260 // as we are not interested in them.
Tobias Grosser78a84942018-06-01 19:12:00 +00001261 OnlyDimS = OnlyDimS.insert_dims(isl::dim::param, 0, Dim);
1262
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001263 for (unsigned u = 0; u < Dim; u++) {
Tobias Grosser78a84942018-06-01 19:12:00 +00001264 isl::constraint C = isl::constraint::alloc_inequality(
1265 isl::local_space(OnlyDimS.get_space()));
1266 C = C.set_coefficient_si(isl::dim::param, u, 1);
1267 C = C.set_coefficient_si(isl::dim::set, u, -1);
1268 OnlyDimS = OnlyDimS.add_constraint(C);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001269 }
1270
1271 // Collect all bounded parts of OnlyDimS.
Tobias Grosser78a84942018-06-01 19:12:00 +00001272 isl::set BoundedParts = collectBoundedParts(OnlyDimS);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001273
1274 // Create the dimensions greater than Dim again.
Tobias Grosser78a84942018-06-01 19:12:00 +00001275 BoundedParts =
1276 BoundedParts.insert_dims(isl::dim::set, Dim + 1, NumDimsS - Dim - 1);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001277
1278 // Remove the artificial upper bound parameters again.
Tobias Grosser78a84942018-06-01 19:12:00 +00001279 BoundedParts = BoundedParts.remove_dims(isl::dim::param, 0, Dim);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001280
Tobias Grosser78a84942018-06-01 19:12:00 +00001281 isl::set UnboundedParts = S.subtract(BoundedParts);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00001282 return std::make_pair(UnboundedParts, BoundedParts);
1283}
1284
Tobias Grosserc80d6972016-09-02 06:33:33 +00001285/// Create the conditions under which @p L @p Pred @p R is true.
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001286static isl::set buildConditionSet(ICmpInst::Predicate Pred, isl::pw_aff L,
1287 isl::pw_aff R) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00001288 switch (Pred) {
1289 case ICmpInst::ICMP_EQ:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001290 return L.eq_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001291 case ICmpInst::ICMP_NE:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001292 return L.ne_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001293 case ICmpInst::ICMP_SLT:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001294 return L.lt_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001295 case ICmpInst::ICMP_SLE:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001296 return L.le_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001297 case ICmpInst::ICMP_SGT:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001298 return L.gt_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001299 case ICmpInst::ICMP_SGE:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001300 return L.ge_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001301 case ICmpInst::ICMP_ULT:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001302 return L.lt_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001303 case ICmpInst::ICMP_UGT:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001304 return L.gt_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001305 case ICmpInst::ICMP_ULE:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001306 return L.le_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001307 case ICmpInst::ICMP_UGE:
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001308 return L.ge_set(R);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001309 default:
1310 llvm_unreachable("Non integer predicate not supported");
1311 }
1312}
1313
Michael Kruse476f8552017-06-29 12:47:41 +00001314/// Compute the isl representation for the SCEV @p E in this BB.
1315///
1316/// @param S The Scop in which @p BB resides in.
1317/// @param BB The BB for which isl representation is to be
1318/// computed.
1319/// @param InvalidDomainMap A map of BB to their invalid domains.
1320/// @param E The SCEV that should be translated.
1321/// @param NonNegative Flag to indicate the @p E has to be non-negative.
1322///
1323/// Note that this function will also adjust the invalid context accordingly.
1324
1325__isl_give isl_pw_aff *
1326getPwAff(Scop &S, BasicBlock *BB,
Tobias Grosser13acbb92017-07-15 09:01:31 +00001327 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap, const SCEV *E,
1328 bool NonNegative = false) {
Michael Kruse476f8552017-06-29 12:47:41 +00001329 PWACtx PWAC = S.getPwAff(E, BB, NonNegative);
Philip Pfaffed98dbee2017-12-06 21:02:22 +00001330 InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
Tobias Grosser8dae41a2018-04-29 00:57:38 +00001331 return PWAC.first.release();
Michael Kruse476f8552017-06-29 12:47:41 +00001332}
1333
Tobias Grosserc80d6972016-09-02 06:33:33 +00001334/// Build the conditions sets for the switch @p SI in the @p Domain.
Johannes Doerfert96425c22015-08-30 21:13:53 +00001335///
1336/// This will fill @p ConditionSets with the conditions under which control
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001337/// will be moved from @p SI to its successors. Hence, @p ConditionSets will
1338/// have as many elements as @p SI has successors.
Tobias Grosseree457592017-09-24 09:25:30 +00001339bool buildConditionSets(Scop &S, BasicBlock *BB, SwitchInst *SI, Loop *L,
1340 __isl_keep isl_set *Domain,
1341 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1342 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001343 Value *Condition = getConditionFromTerminator(SI);
1344 assert(Condition && "No condition for switch");
1345
1346 ScalarEvolution &SE = *S.getSE();
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001347 isl_pw_aff *LHS, *RHS;
Michael Kruse476f8552017-06-29 12:47:41 +00001348 LHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEVAtScope(Condition, L));
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001349
1350 unsigned NumSuccessors = SI->getNumSuccessors();
1351 ConditionSets.resize(NumSuccessors);
1352 for (auto &Case : SI->cases()) {
1353 unsigned Idx = Case.getSuccessorIndex();
1354 ConstantInt *CaseValue = Case.getCaseValue();
1355
Michael Kruse476f8552017-06-29 12:47:41 +00001356 RHS = getPwAff(S, BB, InvalidDomainMap, SE.getSCEV(CaseValue));
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001357 isl_set *CaseConditionSet =
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001358 buildConditionSet(ICmpInst::ICMP_EQ, isl::manage_copy(LHS),
1359 isl::manage(RHS))
1360 .release();
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001361 ConditionSets[Idx] = isl_set_coalesce(
1362 isl_set_intersect(CaseConditionSet, isl_set_copy(Domain)));
1363 }
1364
1365 assert(ConditionSets[0] == nullptr && "Default condition set was set");
1366 isl_set *ConditionSetUnion = isl_set_copy(ConditionSets[1]);
1367 for (unsigned u = 2; u < NumSuccessors; u++)
1368 ConditionSetUnion =
1369 isl_set_union(ConditionSetUnion, isl_set_copy(ConditionSets[u]));
Tobias Grosserb9486302018-03-03 19:27:54 +00001370 ConditionSets[0] = isl_set_subtract(isl_set_copy(Domain), ConditionSetUnion);
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001371
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001372 isl_pw_aff_free(LHS);
Johannes Doerfert297c7202016-05-10 13:06:42 +00001373
1374 return true;
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001375}
1376
Michael Kruse08655852017-07-20 12:37:02 +00001377/// Build condition sets for unsigned ICmpInst(s).
1378/// Special handling is required for unsigned operands to ensure that if
1379/// MSB (aka the Sign bit) is set for an operands in an unsigned ICmpInst
1380/// it should wrap around.
1381///
1382/// @param IsStrictUpperBound holds information on the predicate relation
1383/// between TestVal and UpperBound, i.e,
1384/// TestVal < UpperBound OR TestVal <= UpperBound
Tobias Grosseree457592017-09-24 09:25:30 +00001385__isl_give isl_set *
Michael Kruse08655852017-07-20 12:37:02 +00001386buildUnsignedConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
1387 __isl_keep isl_set *Domain, const SCEV *SCEV_TestVal,
1388 const SCEV *SCEV_UpperBound,
1389 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1390 bool IsStrictUpperBound) {
Michael Kruse08655852017-07-20 12:37:02 +00001391 // Do not take NonNeg assumption on TestVal
1392 // as it might have MSB (Sign bit) set.
1393 isl_pw_aff *TestVal = getPwAff(S, BB, InvalidDomainMap, SCEV_TestVal, false);
1394 // Take NonNeg assumption on UpperBound.
1395 isl_pw_aff *UpperBound =
1396 getPwAff(S, BB, InvalidDomainMap, SCEV_UpperBound, true);
1397
1398 // 0 <= TestVal
1399 isl_set *First =
1400 isl_pw_aff_le_set(isl_pw_aff_zero_on_domain(isl_local_space_from_space(
1401 isl_pw_aff_get_domain_space(TestVal))),
1402 isl_pw_aff_copy(TestVal));
1403
1404 isl_set *Second;
1405 if (IsStrictUpperBound)
1406 // TestVal < UpperBound
1407 Second = isl_pw_aff_lt_set(TestVal, UpperBound);
1408 else
1409 // TestVal <= UpperBound
1410 Second = isl_pw_aff_le_set(TestVal, UpperBound);
1411
1412 isl_set *ConsequenceCondSet = isl_set_intersect(First, Second);
Michael Kruse08655852017-07-20 12:37:02 +00001413 return ConsequenceCondSet;
1414}
1415
Tobias Grosserc80d6972016-09-02 06:33:33 +00001416/// Build the conditions sets for the branch condition @p Condition in
1417/// the @p Domain.
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001418///
1419/// This will fill @p ConditionSets with the conditions under which control
1420/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001421/// have as many elements as @p TI has successors. If @p TI is nullptr the
1422/// context under which @p Condition is true/false will be returned as the
1423/// new elements of @p ConditionSets.
Tobias Grosseree457592017-09-24 09:25:30 +00001424bool buildConditionSets(Scop &S, BasicBlock *BB, Value *Condition,
Chandler Carruthe303c872018-10-15 10:42:50 +00001425 Instruction *TI, Loop *L, __isl_keep isl_set *Domain,
Tobias Grosseree457592017-09-24 09:25:30 +00001426 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1427 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
Tobias Grosser5e531df2017-09-25 20:27:15 +00001428 ScalarEvolution &SE = *S.getSE();
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001429 isl_set *ConsequenceCondSet = nullptr;
Tobias Grosser0a62b2d2017-09-25 16:37:15 +00001430
Tobias Grosser5e531df2017-09-25 20:27:15 +00001431 if (auto Load = dyn_cast<LoadInst>(Condition)) {
1432 const SCEV *LHSSCEV = SE.getSCEVAtScope(Load, L);
1433 const SCEV *RHSSCEV = SE.getZero(LHSSCEV->getType());
1434 bool NonNeg = false;
1435 isl_pw_aff *LHS = getPwAff(S, BB, InvalidDomainMap, LHSSCEV, NonNeg);
1436 isl_pw_aff *RHS = getPwAff(S, BB, InvalidDomainMap, RHSSCEV, NonNeg);
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001437 ConsequenceCondSet = buildConditionSet(ICmpInst::ICMP_SLE, isl::manage(LHS),
1438 isl::manage(RHS))
1439 .release();
Tobias Grosser5e531df2017-09-25 20:27:15 +00001440 } else if (auto *PHI = dyn_cast<PHINode>(Condition)) {
Tobias Grosser0a62b2d2017-09-25 16:37:15 +00001441 auto *Unique = dyn_cast<ConstantInt>(
1442 getUniqueNonErrorValue(PHI, &S.getRegion(), *S.getLI(), *S.getDT()));
1443
1444 if (Unique->isZero())
1445 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
1446 else
1447 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
1448 } else if (auto *CCond = dyn_cast<ConstantInt>(Condition)) {
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001449 if (CCond->isZero())
1450 ConsequenceCondSet = isl_set_empty(isl_set_get_space(Domain));
1451 else
1452 ConsequenceCondSet = isl_set_universe(isl_set_get_space(Domain));
1453 } else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(Condition)) {
1454 auto Opcode = BinOp->getOpcode();
1455 assert(Opcode == Instruction::And || Opcode == Instruction::Or);
1456
Michael Kruse476f8552017-06-29 12:47:41 +00001457 bool Valid = buildConditionSets(S, BB, BinOp->getOperand(0), TI, L, Domain,
1458 InvalidDomainMap, ConditionSets) &&
1459 buildConditionSets(S, BB, BinOp->getOperand(1), TI, L, Domain,
1460 InvalidDomainMap, ConditionSets);
Johannes Doerfertede4eca2016-05-10 14:01:21 +00001461 if (!Valid) {
1462 while (!ConditionSets.empty())
1463 isl_set_free(ConditionSets.pop_back_val());
Johannes Doerfert297c7202016-05-10 13:06:42 +00001464 return false;
Johannes Doerfertede4eca2016-05-10 14:01:21 +00001465 }
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001466
1467 isl_set_free(ConditionSets.pop_back_val());
1468 isl_set *ConsCondPart0 = ConditionSets.pop_back_val();
1469 isl_set_free(ConditionSets.pop_back_val());
1470 isl_set *ConsCondPart1 = ConditionSets.pop_back_val();
1471
1472 if (Opcode == Instruction::And)
1473 ConsequenceCondSet = isl_set_intersect(ConsCondPart0, ConsCondPart1);
1474 else
1475 ConsequenceCondSet = isl_set_union(ConsCondPart0, ConsCondPart1);
1476 } else {
1477 auto *ICond = dyn_cast<ICmpInst>(Condition);
1478 assert(ICond &&
1479 "Condition of exiting branch was neither constant nor ICmp!");
1480
Tobias Grosseree457592017-09-24 09:25:30 +00001481 LoopInfo &LI = *S.getLI();
1482 DominatorTree &DT = *S.getDT();
1483 Region &R = S.getRegion();
1484
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001485 isl_pw_aff *LHS, *RHS;
Johannes Doerfert3e48ee22016-04-29 10:44:41 +00001486 // For unsigned comparisons we assumed the signed bit of neither operand
1487 // to be set. The comparison is equal to a signed comparison under this
1488 // assumption.
1489 bool NonNeg = ICond->isUnsigned();
Michael Kruse08655852017-07-20 12:37:02 +00001490 const SCEV *LeftOperand = SE.getSCEVAtScope(ICond->getOperand(0), L),
1491 *RightOperand = SE.getSCEVAtScope(ICond->getOperand(1), L);
1492
Tobias Grosseree457592017-09-24 09:25:30 +00001493 LeftOperand = tryForwardThroughPHI(LeftOperand, R, SE, LI, DT);
1494 RightOperand = tryForwardThroughPHI(RightOperand, R, SE, LI, DT);
1495
Michael Kruse08655852017-07-20 12:37:02 +00001496 switch (ICond->getPredicate()) {
1497 case ICmpInst::ICMP_ULT:
1498 ConsequenceCondSet =
1499 buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand,
1500 RightOperand, InvalidDomainMap, true);
1501 break;
1502 case ICmpInst::ICMP_ULE:
1503 ConsequenceCondSet =
1504 buildUnsignedConditionSets(S, BB, Condition, Domain, LeftOperand,
1505 RightOperand, InvalidDomainMap, false);
1506 break;
1507 case ICmpInst::ICMP_UGT:
1508 ConsequenceCondSet =
1509 buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand,
1510 LeftOperand, InvalidDomainMap, true);
1511 break;
1512 case ICmpInst::ICMP_UGE:
1513 ConsequenceCondSet =
1514 buildUnsignedConditionSets(S, BB, Condition, Domain, RightOperand,
1515 LeftOperand, InvalidDomainMap, false);
1516 break;
1517 default:
1518 LHS = getPwAff(S, BB, InvalidDomainMap, LeftOperand, NonNeg);
1519 RHS = getPwAff(S, BB, InvalidDomainMap, RightOperand, NonNeg);
Tobias Grosserfd5c8562018-06-18 12:35:36 +00001520 ConsequenceCondSet = buildConditionSet(ICond->getPredicate(),
1521 isl::manage(LHS), isl::manage(RHS))
1522 .release();
Michael Kruse08655852017-07-20 12:37:02 +00001523 break;
1524 }
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001525 }
1526
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001527 // If no terminator was given we are only looking for parameter constraints
1528 // under which @p Condition is true/false.
1529 if (!TI)
1530 ConsequenceCondSet = isl_set_params(ConsequenceCondSet);
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001531 assert(ConsequenceCondSet);
Johannes Doerfert15194912016-04-04 07:59:41 +00001532 ConsequenceCondSet = isl_set_coalesce(
1533 isl_set_intersect(ConsequenceCondSet, isl_set_copy(Domain)));
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001534
Johannes Doerfertb2885792016-04-26 09:20:41 +00001535 isl_set *AlternativeCondSet = nullptr;
Michael Krusef7a4a942016-05-02 12:25:36 +00001536 bool TooComplex =
Tobias Grosser90411a92017-02-16 19:11:33 +00001537 isl_set_n_basic_set(ConsequenceCondSet) >= MaxDisjunctsInDomain;
Johannes Doerfertb2885792016-04-26 09:20:41 +00001538
Michael Krusef7a4a942016-05-02 12:25:36 +00001539 if (!TooComplex) {
Johannes Doerfert15194912016-04-04 07:59:41 +00001540 AlternativeCondSet = isl_set_subtract(isl_set_copy(Domain),
1541 isl_set_copy(ConsequenceCondSet));
Michael Krusef7a4a942016-05-02 12:25:36 +00001542 TooComplex =
Tobias Grosser90411a92017-02-16 19:11:33 +00001543 isl_set_n_basic_set(AlternativeCondSet) >= MaxDisjunctsInDomain;
Johannes Doerfertb2885792016-04-26 09:20:41 +00001544 }
1545
Michael Krusef7a4a942016-05-02 12:25:36 +00001546 if (TooComplex) {
Eli Friedmane737fc12017-07-17 23:58:33 +00001547 S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc(),
1548 TI ? TI->getParent() : nullptr /* BasicBlock */);
Johannes Doerfertb2885792016-04-26 09:20:41 +00001549 isl_set_free(AlternativeCondSet);
Johannes Doerfertb2885792016-04-26 09:20:41 +00001550 isl_set_free(ConsequenceCondSet);
Johannes Doerfert297c7202016-05-10 13:06:42 +00001551 return false;
Johannes Doerfert15194912016-04-04 07:59:41 +00001552 }
1553
1554 ConditionSets.push_back(ConsequenceCondSet);
1555 ConditionSets.push_back(isl_set_coalesce(AlternativeCondSet));
Johannes Doerfert297c7202016-05-10 13:06:42 +00001556
1557 return true;
Johannes Doerfert9b1f9c82015-10-11 13:21:03 +00001558}
1559
Tobias Grosserc80d6972016-09-02 06:33:33 +00001560/// Build the conditions sets for the terminator @p TI in the @p Domain.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001561///
1562/// This will fill @p ConditionSets with the conditions under which control
1563/// will be moved from @p TI to its successors. Hence, @p ConditionSets will
1564/// have as many elements as @p TI has successors.
Chandler Carruthe303c872018-10-15 10:42:50 +00001565bool buildConditionSets(Scop &S, BasicBlock *BB, Instruction *TI, Loop *L,
Tobias Grosseree457592017-09-24 09:25:30 +00001566 __isl_keep isl_set *Domain,
1567 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
1568 SmallVectorImpl<__isl_give isl_set *> &ConditionSets) {
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001569 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI))
Michael Kruse476f8552017-06-29 12:47:41 +00001570 return buildConditionSets(S, BB, SI, L, Domain, InvalidDomainMap,
1571 ConditionSets);
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001572
1573 assert(isa<BranchInst>(TI) && "Terminator was neither branch nor switch.");
1574
1575 if (TI->getNumSuccessors() == 1) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00001576 ConditionSets.push_back(isl_set_copy(Domain));
Johannes Doerfert297c7202016-05-10 13:06:42 +00001577 return true;
Johannes Doerfert96425c22015-08-30 21:13:53 +00001578 }
1579
Johannes Doerfert9a132f32015-09-28 09:33:22 +00001580 Value *Condition = getConditionFromTerminator(TI);
1581 assert(Condition && "No condition for Terminator");
Johannes Doerfert96425c22015-08-30 21:13:53 +00001582
Michael Kruse476f8552017-06-29 12:47:41 +00001583 return buildConditionSets(S, BB, Condition, TI, L, Domain, InvalidDomainMap,
1584 ConditionSets);
Johannes Doerfert96425c22015-08-30 21:13:53 +00001585}
1586
Michael Krused6e22082018-01-18 15:15:38 +00001587ScopStmt::ScopStmt(Scop &parent, Region &R, StringRef Name,
1588 Loop *SurroundingLoop,
Tobias Grosserbd15d132017-08-31 03:15:56 +00001589 std::vector<Instruction *> EntryBlockInstructions)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001590 : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), R(&R),
Michael Krused6e22082018-01-18 15:15:38 +00001591 Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop),
1592 Instructions(EntryBlockInstructions) {}
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001593
Michael Krused6e22082018-01-18 15:15:38 +00001594ScopStmt::ScopStmt(Scop &parent, BasicBlock &bb, StringRef Name,
1595 Loop *SurroundingLoop,
1596 std::vector<Instruction *> Instructions)
Johannes Doerferta3519512016-04-23 13:02:23 +00001597 : Parent(parent), InvalidDomain(nullptr), Domain(nullptr), BB(&bb),
Michael Krused6e22082018-01-18 15:15:38 +00001598 Build(nullptr), BaseName(Name), SurroundingLoop(SurroundingLoop),
1599 Instructions(Instructions) {}
Michael Krusecac948e2015-10-02 13:53:07 +00001600
Tobias Grosser85048ef2017-08-06 17:24:59 +00001601ScopStmt::ScopStmt(Scop &parent, isl::map SourceRel, isl::map TargetRel,
1602 isl::set NewDomain)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001603 : Parent(parent), InvalidDomain(nullptr), Domain(NewDomain),
1604 Build(nullptr) {
Roman Gareevb3224ad2016-09-14 06:26:09 +00001605 BaseName = getIslCompatibleName("CopyStmt_", "",
1606 std::to_string(parent.getCopyStmtsNum()));
Tobias Grosser85048ef2017-08-06 17:24:59 +00001607 isl::id Id = isl::id::alloc(getIslCtx(), getBaseName(), this);
1608 Domain = Domain.set_tuple_id(Id);
1609 TargetRel = TargetRel.set_tuple_id(isl::dim::in, Id);
1610 auto *Access =
1611 new MemoryAccess(this, MemoryAccess::AccessType::MUST_WRITE, TargetRel);
Roman Gareevb3224ad2016-09-14 06:26:09 +00001612 parent.addAccessFunction(Access);
1613 addAccess(Access);
Tobias Grosser85048ef2017-08-06 17:24:59 +00001614 SourceRel = SourceRel.set_tuple_id(isl::dim::in, Id);
1615 Access = new MemoryAccess(this, MemoryAccess::AccessType::READ, SourceRel);
Roman Gareevb3224ad2016-09-14 06:26:09 +00001616 parent.addAccessFunction(Access);
1617 addAccess(Access);
1618}
1619
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001620ScopStmt::~ScopStmt() = default;
1621
Tobias Grossera9b5bba2017-08-06 16:11:53 +00001622std::string ScopStmt::getDomainStr() const { return Domain.to_str(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001623
Tobias Grosser54839312015-04-21 11:37:25 +00001624std::string ScopStmt::getScheduleStr() const {
Tobias Grosser6ad16402017-08-06 17:45:28 +00001625 auto *S = getSchedule().release();
Roman Gareevb3224ad2016-09-14 06:26:09 +00001626 if (!S)
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001627 return {};
Tobias Grosser808cd692015-07-14 09:33:13 +00001628 auto Str = stringFromIslObj(S);
1629 isl_map_free(S);
1630 return Str;
Tobias Grosser75805372011-04-29 06:27:02 +00001631}
1632
Tobias Grosser2332fa32017-08-06 15:36:48 +00001633void ScopStmt::setInvalidDomain(isl::set ID) { InvalidDomain = ID; }
Johannes Doerfert7c013572016-04-12 09:57:34 +00001634
Michael Kruse375cb5f2016-02-24 22:08:24 +00001635BasicBlock *ScopStmt::getEntryBlock() const {
1636 if (isBlockStmt())
1637 return getBasicBlock();
1638 return getRegion()->getEntry();
1639}
1640
Tobias Grosserf567e1a2015-02-19 22:16:12 +00001641unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001642
Tobias Grosser75805372011-04-29 06:27:02 +00001643const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
1644
Johannes Doerfert2b92a0e2016-05-10 14:00:57 +00001645Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
Sebastian Pop860e0212013-02-15 21:26:44 +00001646 return NestLoops[Dimension];
Tobias Grosser75805372011-04-29 06:27:02 +00001647}
1648
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00001649isl::ctx ScopStmt::getIslCtx() const { return Parent.getIslCtx(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001650
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001651isl::set ScopStmt::getDomain() const { return Domain; }
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +00001652
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001653isl::space ScopStmt::getDomainSpace() const { return Domain.get_space(); }
Tobias Grosser78d8a3d2012-01-17 20:34:23 +00001654
Tobias Grosserdcf8d692017-08-06 16:39:52 +00001655isl::id ScopStmt::getDomainId() const { return Domain.get_tuple_id(); }
Tobias Grossercd95b772012-08-30 11:49:38 +00001656
Tobias Grosserd5fcbef2017-05-27 04:40:18 +00001657void ScopStmt::printInstructions(raw_ostream &OS) const {
1658 OS << "Instructions {\n";
1659
1660 for (Instruction *Inst : Instructions)
1661 OS.indent(16) << *Inst << "\n";
1662
Michael Krusee52ebd12017-07-22 16:44:39 +00001663 OS.indent(12) << "}\n";
Tobias Grosserd5fcbef2017-05-27 04:40:18 +00001664}
1665
Michael Krusecd4c9772017-07-21 15:35:53 +00001666void ScopStmt::print(raw_ostream &OS, bool PrintInstructions) const {
Tobias Grosser75805372011-04-29 06:27:02 +00001667 OS << "\t" << getBaseName() << "\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001668 OS.indent(12) << "Domain :=\n";
1669
1670 if (Domain) {
1671 OS.indent(16) << getDomainStr() << ";\n";
1672 } else
1673 OS.indent(16) << "n/a\n";
1674
Tobias Grosser54839312015-04-21 11:37:25 +00001675 OS.indent(12) << "Schedule :=\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001676
1677 if (Domain) {
Tobias Grosser54839312015-04-21 11:37:25 +00001678 OS.indent(16) << getScheduleStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001679 } else
1680 OS.indent(16) << "n/a\n";
1681
Tobias Grosser083d3d32014-06-28 08:59:45 +00001682 for (MemoryAccess *Access : MemAccs)
1683 Access->print(OS);
Tobias Grosserd5fcbef2017-05-27 04:40:18 +00001684
Tobias Grosserbd15d132017-08-31 03:15:56 +00001685 if (PrintInstructions)
Tobias Grosserd5fcbef2017-05-27 04:40:18 +00001686 printInstructions(OS.indent(12));
Tobias Grosser75805372011-04-29 06:27:02 +00001687}
1688
Michael Kruse5d518462017-07-21 15:54:07 +00001689#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Michael Krusee1860132017-07-21 15:54:13 +00001690LLVM_DUMP_METHOD void ScopStmt::dump() const { print(dbgs(), true); }
Michael Kruse5d518462017-07-21 15:54:07 +00001691#endif
Tobias Grosser75805372011-04-29 06:27:02 +00001692
Michael Krusee60eca72017-05-11 22:56:12 +00001693void ScopStmt::removeAccessData(MemoryAccess *MA) {
1694 if (MA->isRead() && MA->isOriginalValueKind()) {
1695 bool Found = ValueReads.erase(MA->getAccessValue());
1696 (void)Found;
1697 assert(Found && "Expected access data not found");
1698 }
1699 if (MA->isWrite() && MA->isOriginalValueKind()) {
1700 bool Found = ValueWrites.erase(cast<Instruction>(MA->getAccessValue()));
1701 (void)Found;
1702 assert(Found && "Expected access data not found");
1703 }
1704 if (MA->isWrite() && MA->isOriginalAnyPHIKind()) {
1705 bool Found = PHIWrites.erase(cast<PHINode>(MA->getAccessInstruction()));
1706 (void)Found;
1707 assert(Found && "Expected access data not found");
1708 }
Michael Kruse3562f272017-07-20 16:47:57 +00001709 if (MA->isRead() && MA->isOriginalAnyPHIKind()) {
1710 bool Found = PHIReads.erase(cast<PHINode>(MA->getAccessInstruction()));
1711 (void)Found;
1712 assert(Found && "Expected access data not found");
1713 }
Michael Krusee60eca72017-05-11 22:56:12 +00001714}
1715
Michael Kruse10071822016-05-23 14:45:58 +00001716void ScopStmt::removeMemoryAccess(MemoryAccess *MA) {
Tobias Grosser4d5a9172017-01-14 20:25:44 +00001717 // Remove the memory accesses from this statement together with all scalar
1718 // accesses that were caused by it. MemoryKind::Value READs have no access
1719 // instruction, hence would not be removed by this function. However, it is
1720 // only used for invariant LoadInst accesses, its arguments are always affine,
1721 // hence synthesizable, and therefore there are no MemoryKind::Value READ
1722 // accesses to be removed.
Michael Kruse10071822016-05-23 14:45:58 +00001723 auto Predicate = [&](MemoryAccess *Acc) {
1724 return Acc->getAccessInstruction() == MA->getAccessInstruction();
1725 };
Michael Krusee60eca72017-05-11 22:56:12 +00001726 for (auto *MA : MemAccs) {
Michael Kruse8b805802017-07-19 17:11:25 +00001727 if (Predicate(MA)) {
Michael Krusee60eca72017-05-11 22:56:12 +00001728 removeAccessData(MA);
Michael Kruse8b805802017-07-19 17:11:25 +00001729 Parent.removeAccessData(MA);
1730 }
Michael Krusee60eca72017-05-11 22:56:12 +00001731 }
Michael Kruse10071822016-05-23 14:45:58 +00001732 MemAccs.erase(std::remove_if(MemAccs.begin(), MemAccs.end(), Predicate),
1733 MemAccs.end());
1734 InstructionToAccess.erase(MA->getAccessInstruction());
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00001735}
1736
Michael Kruse192e7f72018-04-09 23:13:05 +00001737void ScopStmt::removeSingleMemoryAccess(MemoryAccess *MA, bool AfterHoisting) {
1738 if (AfterHoisting) {
1739 auto MAIt = std::find(MemAccs.begin(), MemAccs.end(), MA);
1740 assert(MAIt != MemAccs.end());
1741 MemAccs.erase(MAIt);
Michael Kruse0446d812017-03-10 16:05:24 +00001742
Michael Kruse192e7f72018-04-09 23:13:05 +00001743 removeAccessData(MA);
1744 Parent.removeAccessData(MA);
1745 }
Michael Krusee60eca72017-05-11 22:56:12 +00001746
Michael Kruse0446d812017-03-10 16:05:24 +00001747 auto It = InstructionToAccess.find(MA->getAccessInstruction());
1748 if (It != InstructionToAccess.end()) {
1749 It->second.remove(MA);
1750 if (It->second.empty())
1751 InstructionToAccess.erase(MA->getAccessInstruction());
1752 }
1753}
1754
Michael Kruse07e8c362017-07-24 12:43:27 +00001755MemoryAccess *ScopStmt::ensureValueRead(Value *V) {
1756 MemoryAccess *Access = lookupInputAccessOf(V);
1757 if (Access)
1758 return Access;
1759
1760 ScopArrayInfo *SAI =
1761 Parent.getOrCreateScopArrayInfo(V, V->getType(), {}, MemoryKind::Value);
1762 Access = new MemoryAccess(this, nullptr, MemoryAccess::READ, V, V->getType(),
1763 true, {}, {}, V, MemoryKind::Value);
1764 Parent.addAccessFunction(Access);
1765 Access->buildAccessRelation(SAI);
1766 addAccess(Access);
1767 Parent.addAccessData(Access);
1768 return Access;
1769}
1770
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001771raw_ostream &polly::operator<<(raw_ostream &OS, const ScopStmt &S) {
1772 S.print(OS, PollyPrintInstructions);
1773 return OS;
Michael Krusecd4c9772017-07-21 15:35:53 +00001774}
1775
Tobias Grosser75805372011-04-29 06:27:02 +00001776//===----------------------------------------------------------------------===//
1777/// Scop class implement
Tobias Grosser60b54f12011-11-08 15:41:28 +00001778
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00001779void Scop::setContext(isl::set NewContext) {
1780 Context = NewContext.align_params(Context.get_space());
Tobias Grosserff9b54d2011-11-15 11:38:44 +00001781}
1782
Eli Friedman5e589ea2017-06-20 22:53:02 +00001783namespace {
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001784
Tobias Grosserc80d6972016-09-02 06:33:33 +00001785/// Remap parameter values but keep AddRecs valid wrt. invariant loads.
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001786struct SCEVSensitiveParameterRewriter
Tobias Grosser278f9e72016-11-26 17:58:40 +00001787 : public SCEVRewriteVisitor<SCEVSensitiveParameterRewriter> {
Tobias Grosserb5563c62017-08-03 13:51:15 +00001788 const ValueToValueMap &VMap;
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001789
1790public:
Tobias Grosserb5563c62017-08-03 13:51:15 +00001791 SCEVSensitiveParameterRewriter(const ValueToValueMap &VMap,
1792 ScalarEvolution &SE)
Tobias Grosser278f9e72016-11-26 17:58:40 +00001793 : SCEVRewriteVisitor(SE), VMap(VMap) {}
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001794
1795 static const SCEV *rewrite(const SCEV *E, ScalarEvolution &SE,
Tobias Grosserb5563c62017-08-03 13:51:15 +00001796 const ValueToValueMap &VMap) {
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001797 SCEVSensitiveParameterRewriter SSPR(VMap, SE);
1798 return SSPR.visit(E);
1799 }
1800
Johannes Doerfertd6fc0702015-11-03 16:47:58 +00001801 const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {
1802 auto *Start = visit(E->getStart());
1803 auto *AddRec = SE.getAddRecExpr(SE.getConstant(E->getType(), 0),
1804 visit(E->getStepRecurrence(SE)),
1805 E->getLoop(), SCEV::FlagAnyWrap);
1806 return SE.getAddExpr(Start, AddRec);
1807 }
1808
1809 const SCEV *visitUnknown(const SCEVUnknown *E) {
1810 if (auto *NewValue = VMap.lookup(E->getValue()))
1811 return SE.getUnknown(NewValue);
1812 return E;
1813 }
1814};
1815
Eli Friedman5e589ea2017-06-20 22:53:02 +00001816/// Check whether we should remap a SCEV expression.
1817struct SCEVFindInsideScop : public SCEVTraversal<SCEVFindInsideScop> {
Tobias Grosserb5563c62017-08-03 13:51:15 +00001818 const ValueToValueMap &VMap;
Eli Friedman5e589ea2017-06-20 22:53:02 +00001819 bool FoundInside = false;
Tobias Grosserb5563c62017-08-03 13:51:15 +00001820 const Scop *S;
Eli Friedman5e589ea2017-06-20 22:53:02 +00001821
1822public:
Tobias Grosserb5563c62017-08-03 13:51:15 +00001823 SCEVFindInsideScop(const ValueToValueMap &VMap, ScalarEvolution &SE,
1824 const Scop *S)
Eli Friedman5e589ea2017-06-20 22:53:02 +00001825 : SCEVTraversal(*this), VMap(VMap), S(S) {}
1826
1827 static bool hasVariant(const SCEV *E, ScalarEvolution &SE,
Tobias Grosserb5563c62017-08-03 13:51:15 +00001828 const ValueToValueMap &VMap, const Scop *S) {
Eli Friedman5e589ea2017-06-20 22:53:02 +00001829 SCEVFindInsideScop SFIS(VMap, SE, S);
1830 SFIS.visitAll(E);
1831 return SFIS.FoundInside;
1832 }
1833
1834 bool follow(const SCEV *E) {
1835 if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(E)) {
1836 FoundInside |= S->getRegion().contains(AddRec->getLoop());
1837 } else if (auto *Unknown = dyn_cast<SCEVUnknown>(E)) {
1838 if (Instruction *I = dyn_cast<Instruction>(Unknown->getValue()))
1839 FoundInside |= S->getRegion().contains(I) && !VMap.count(I);
1840 }
1841 return !FoundInside;
1842 }
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001843
Eli Friedman5e589ea2017-06-20 22:53:02 +00001844 bool isDone() { return FoundInside; }
1845};
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001846} // end anonymous namespace
Eli Friedman5e589ea2017-06-20 22:53:02 +00001847
Tobias Grosserb5563c62017-08-03 13:51:15 +00001848const SCEV *Scop::getRepresentingInvariantLoadSCEV(const SCEV *E) const {
Eli Friedman5e589ea2017-06-20 22:53:02 +00001849 // Check whether it makes sense to rewrite the SCEV. (ScalarEvolution
1850 // doesn't like addition between an AddRec and an expression that
1851 // doesn't have a dominance relationship with it.)
1852 if (SCEVFindInsideScop::hasVariant(E, *SE, InvEquivClassVMap, this))
1853 return E;
1854
1855 // Rewrite SCEV.
1856 return SCEVSensitiveParameterRewriter::rewrite(E, *SE, InvEquivClassVMap);
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001857}
1858
Tobias Grosserf5e7e602017-05-27 15:18:46 +00001859// This table of function names is used to translate parameter names in more
1860// human-readable names. This makes it easier to interpret Polly analysis
1861// results.
1862StringMap<std::string> KnownNames = {
1863 {"_Z13get_global_idj", "global_id"},
1864 {"_Z12get_local_idj", "local_id"},
1865 {"_Z15get_global_sizej", "global_size"},
1866 {"_Z14get_local_sizej", "local_size"},
1867 {"_Z12get_work_dimv", "work_dim"},
1868 {"_Z17get_global_offsetj", "global_offset"},
1869 {"_Z12get_group_idj", "group_id"},
1870 {"_Z14get_num_groupsj", "num_groups"},
1871};
1872
1873static std::string getCallParamName(CallInst *Call) {
1874 std::string Result;
1875 raw_string_ostream OS(Result);
1876 std::string Name = Call->getCalledFunction()->getName();
1877
1878 auto Iterator = KnownNames.find(Name);
1879 if (Iterator != KnownNames.end())
Tobias Grosserdff902f2017-06-01 12:46:51 +00001880 Name = "__" + Iterator->getValue();
Tobias Grosserf5e7e602017-05-27 15:18:46 +00001881 OS << Name;
1882 for (auto &Operand : Call->arg_operands()) {
1883 ConstantInt *Op = cast<ConstantInt>(&Operand);
1884 OS << "_" << Op->getValue();
1885 }
1886 OS.flush();
1887 return Result;
1888}
1889
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00001890void Scop::createParameterId(const SCEV *Parameter) {
1891 assert(Parameters.count(Parameter));
1892 assert(!ParameterIds.count(Parameter));
Johannes Doerfert697fdf82015-10-09 17:12:26 +00001893
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00001894 std::string ParameterName = "p_" + std::to_string(getNumParams() - 1);
Tobias Grosserb39c96a2015-11-17 11:54:51 +00001895
Tobias Grosserf5e7e602017-05-27 15:18:46 +00001896 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1897 Value *Val = ValueParameter->getValue();
1898 CallInst *Call = dyn_cast<CallInst>(Val);
Tobias Grosser8f99c162011-11-15 11:38:55 +00001899
Tobias Grosserf5e7e602017-05-27 15:18:46 +00001900 if (Call && isConstCall(Call)) {
1901 ParameterName = getCallParamName(Call);
1902 } else if (UseInstructionNames) {
Tobias Grossere2ccc3f2017-05-03 20:08:52 +00001903 // If this parameter references a specific Value and this value has a name
1904 // we use this name as it is likely to be unique and more useful than just
1905 // a number.
1906 if (Val->hasName())
1907 ParameterName = Val->getName();
1908 else if (LoadInst *LI = dyn_cast<LoadInst>(Val)) {
1909 auto *LoadOrigin = LI->getPointerOperand()->stripInBoundsOffsets();
1910 if (LoadOrigin->hasName()) {
1911 ParameterName += "_loaded_from_";
1912 ParameterName +=
1913 LI->getPointerOperand()->stripInBoundsOffsets()->getName();
1914 }
Tobias Grosserb39c96a2015-11-17 11:54:51 +00001915 }
1916 }
Tobias Grosser8f99c162011-11-15 11:38:55 +00001917
Tobias Grossere2ccc3f2017-05-03 20:08:52 +00001918 ParameterName = getIslCompatibleName("", ParameterName, "");
1919 }
Tobias Grosser2ea7c6e2016-07-01 13:40:28 +00001920
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00001921 isl::id Id = isl::id::alloc(getIslCtx(), ParameterName,
Tobias Grosser6e78cc62017-08-13 17:54:51 +00001922 const_cast<void *>((const void *)Parameter));
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00001923 ParameterIds[Parameter] = Id;
1924}
1925
1926void Scop::addParams(const ParameterSetTy &NewParameters) {
1927 for (const SCEV *Parameter : NewParameters) {
1928 // Normalize the SCEV to get the representing element for an invariant load.
1929 Parameter = extractConstantFactor(Parameter, *SE).second;
1930 Parameter = getRepresentingInvariantLoadSCEV(Parameter);
1931
1932 if (Parameters.insert(Parameter))
1933 createParameterId(Parameter);
1934 }
1935}
1936
Tobias Grosser9a635702017-08-06 19:31:27 +00001937isl::id Scop::getIdForParam(const SCEV *Parameter) const {
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00001938 // Normalize the SCEV to get the representing element for an invariant load.
1939 Parameter = getRepresentingInvariantLoadSCEV(Parameter);
Tobias Grosser6e78cc62017-08-13 17:54:51 +00001940 return ParameterIds.lookup(Parameter);
Tobias Grosser76c2e322011-11-07 12:58:59 +00001941}
Tobias Grosser75805372011-04-29 06:27:02 +00001942
Johannes Doerferte0b08072016-05-23 12:43:44 +00001943bool Scop::isDominatedBy(const DominatorTree &DT, BasicBlock *BB) const {
1944 return DT.dominates(BB, getEntry());
1945}
1946
Michael Kruse476f8552017-06-29 12:47:41 +00001947void Scop::addUserAssumptions(
1948 AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI,
Tobias Grosser13acbb92017-07-15 09:01:31 +00001949 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Michael Kruse89b1f942017-03-17 13:56:53 +00001950 for (auto &Assumption : AC.assumptions()) {
1951 auto *CI = dyn_cast_or_null<CallInst>(Assumption);
1952 if (!CI || CI->getNumArgOperands() != 1)
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001953 continue;
Johannes Doerfert2b92a0e2016-05-10 14:00:57 +00001954
Michael Kruse89b1f942017-03-17 13:56:53 +00001955 bool InScop = contains(CI);
1956 if (!InScop && !isDominatedBy(DT, CI->getParent()))
1957 continue;
Johannes Doerfert2af10e22015-11-12 03:25:01 +00001958
Michael Kruse89b1f942017-03-17 13:56:53 +00001959 auto *L = LI.getLoopFor(CI->getParent());
1960 auto *Val = CI->getArgOperand(0);
1961 ParameterSetTy DetectedParams;
1962 if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) {
Eli Friedmane737fc12017-07-17 23:58:33 +00001963 ORE.emit(
1964 OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI)
1965 << "Non-affine user assumption ignored.");
Michael Kruse89b1f942017-03-17 13:56:53 +00001966 continue;
Michael Kruse7037fde2016-12-15 09:25:14 +00001967 }
Michael Kruse89b1f942017-03-17 13:56:53 +00001968
1969 // Collect all newly introduced parameters.
1970 ParameterSetTy NewParams;
1971 for (auto *Param : DetectedParams) {
1972 Param = extractConstantFactor(Param, *SE).second;
1973 Param = getRepresentingInvariantLoadSCEV(Param);
1974 if (Parameters.count(Param))
1975 continue;
1976 NewParams.insert(Param);
1977 }
1978
1979 SmallVector<isl_set *, 2> ConditionSets;
1980 auto *TI = InScop ? CI->getParent()->getTerminator() : nullptr;
Michael Kruse1df1aac2017-07-26 13:25:28 +00001981 BasicBlock *BB = InScop ? CI->getParent() : getRegion().getEntry();
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00001982 auto *Dom = InScop ? DomainMap[BB].copy() : Context.copy();
Michael Kruse1df1aac2017-07-26 13:25:28 +00001983 assert(Dom && "Cannot propagate a nullptr.");
1984 bool Valid = buildConditionSets(*this, BB, Val, TI, L, Dom,
1985 InvalidDomainMap, ConditionSets);
Michael Kruse89b1f942017-03-17 13:56:53 +00001986 isl_set_free(Dom);
1987
1988 if (!Valid)
1989 continue;
1990
1991 isl_set *AssumptionCtx = nullptr;
1992 if (InScop) {
1993 AssumptionCtx = isl_set_complement(isl_set_params(ConditionSets[1]));
1994 isl_set_free(ConditionSets[0]);
1995 } else {
1996 AssumptionCtx = isl_set_complement(ConditionSets[1]);
1997 AssumptionCtx = isl_set_intersect(AssumptionCtx, ConditionSets[0]);
1998 }
1999
2000 // Project out newly introduced parameters as they are not otherwise useful.
2001 if (!NewParams.empty()) {
2002 for (unsigned u = 0; u < isl_set_n_param(AssumptionCtx); u++) {
2003 auto *Id = isl_set_get_dim_id(AssumptionCtx, isl_dim_param, u);
2004 auto *Param = static_cast<const SCEV *>(isl_id_get_user(Id));
2005 isl_id_free(Id);
2006
2007 if (!NewParams.count(Param))
2008 continue;
2009
2010 AssumptionCtx =
2011 isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1);
2012 }
2013 }
Eli Friedmane737fc12017-07-17 23:58:33 +00002014 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI)
2015 << "Use user assumption: " << stringFromIslObj(AssumptionCtx));
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002016 Context = Context.intersect(isl::manage(AssumptionCtx));
Johannes Doerfert2af10e22015-11-12 03:25:01 +00002017 }
2018}
2019
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002020void Scop::addUserContext() {
2021 if (UserContextStr.empty())
2022 return;
2023
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002024 isl::set UserContext = isl::set(getIslCtx(), UserContextStr.c_str());
2025 isl::space Space = getParamSpace();
2026 if (Space.dim(isl::dim::param) != UserContext.dim(isl::dim::param)) {
2027 std::string SpaceStr = Space.to_str();
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002028 errs() << "Error: the context provided in -polly-context has not the same "
2029 << "number of dimensions than the computed context. Due to this "
2030 << "mismatch, the -polly-context option is ignored. Please provide "
2031 << "the context in the parameter space: " << SpaceStr << ".\n";
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002032 return;
2033 }
2034
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002035 for (unsigned i = 0; i < Space.dim(isl::dim::param); i++) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002036 std::string NameContext = Context.get_dim_name(isl::dim::param, i);
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002037 std::string NameUserContext = UserContext.get_dim_name(isl::dim::param, i);
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002038
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002039 if (NameContext != NameUserContext) {
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002040 std::string SpaceStr = Space.to_str();
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002041 errs() << "Error: the name of dimension " << i
2042 << " provided in -polly-context "
2043 << "is '" << NameUserContext << "', but the name in the computed "
2044 << "context is '" << NameContext
2045 << "'. Due to this name mismatch, "
2046 << "the -polly-context option is ignored. Please provide "
2047 << "the context in the parameter space: " << SpaceStr << ".\n";
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002048 return;
2049 }
2050
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002051 UserContext = UserContext.set_dim_id(isl::dim::param, i,
2052 Space.get_dim_id(isl::dim::param, i));
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002053 }
2054
Tobias Grosser9b9c7012018-05-28 07:45:25 +00002055 Context = Context.intersect(UserContext);
Tobias Grosser8a9c2352015-08-16 10:19:29 +00002056}
2057
Tobias Grosser6be480c2011-11-08 15:41:13 +00002058void Scop::buildContext() {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002059 isl::space Space = isl::space::params_alloc(getIslCtx(), 0);
2060 Context = isl::set::universe(Space);
2061 InvalidContext = isl::set::empty(Space);
2062 AssumedContext = isl::set::universe(Space);
Tobias Grosser0e27e242011-10-06 00:03:48 +00002063}
2064
Tobias Grosser18daaca2012-05-22 10:47:27 +00002065void Scop::addParameterBounds() {
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00002066 unsigned PDim = 0;
2067 for (auto *Parameter : Parameters) {
2068 ConstantRange SRange = SE->getSignedRange(Parameter);
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002069 Context = addRangeBoundsToSet(Context, SRange, PDim++, isl::dim::param);
Tobias Grosser18daaca2012-05-22 10:47:27 +00002070 }
2071}
2072
Tobias Grosserb5563c62017-08-03 13:51:15 +00002073static std::vector<isl::id> getFortranArrayIds(Scop::array_range Arrays) {
2074 std::vector<isl::id> OutermostSizeIds;
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002075 for (auto Array : Arrays) {
2076 // To check if an array is a Fortran array, we check if it has a isl_pw_aff
2077 // for its outermost dimension. Fortran arrays will have this since the
2078 // outermost dimension size can be picked up from their runtime description.
2079 // TODO: actually need to check if it has a FAD, but for now this works.
2080 if (Array->getNumberOfDimensions() > 0) {
Tobias Grosserb5563c62017-08-03 13:51:15 +00002081 isl::pw_aff PwAff = Array->getDimensionSizePw(0);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002082 if (!PwAff)
2083 continue;
2084
Tobias Grosser9b29af92018-06-18 12:49:47 +00002085 isl::id Id = PwAff.get_dim_id(isl::dim::param, 0);
Tobias Grosserb5563c62017-08-03 13:51:15 +00002086 assert(!Id.is_null() &&
2087 "Invalid Id for PwAff expression in Fortran array");
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002088 OutermostSizeIds.push_back(Id);
2089 }
2090 }
Tobias Grosserb5563c62017-08-03 13:51:15 +00002091 return OutermostSizeIds;
2092}
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002093
Tobias Grosserb5563c62017-08-03 13:51:15 +00002094// The FORTRAN array size parameters are known to be non-negative.
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002095static isl::set boundFortranArrayParams(isl::set Context,
Tobias Grosserb5563c62017-08-03 13:51:15 +00002096 Scop::array_range Arrays) {
2097 std::vector<isl::id> OutermostSizeIds;
2098 OutermostSizeIds = getFortranArrayIds(Arrays);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002099
Tobias Grosserb5563c62017-08-03 13:51:15 +00002100 for (isl::id Id : OutermostSizeIds) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002101 int dim = Context.find_dim_by_id(isl::dim::param, Id);
2102 Context = Context.lower_bound_si(isl::dim::param, dim, 0);
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002103 }
2104
2105 return Context;
2106}
2107
Tobias Grosser8cae72f2011-11-08 15:41:08 +00002108void Scop::realignParams() {
Tobias Grosser5842dee2017-03-17 13:00:53 +00002109 if (PollyIgnoreParamBounds)
2110 return;
2111
Tobias Grosser6be480c2011-11-08 15:41:13 +00002112 // Add all parameters into a common model.
Tobias Grosserb5563c62017-08-03 13:51:15 +00002113 isl::space Space = getFullParamSpace();
Tobias Grosser6be480c2011-11-08 15:41:13 +00002114
2115 // Align the parameters of all data structures to the model.
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002116 Context = Context.align_params(Space);
Tobias Grosser6be480c2011-11-08 15:41:13 +00002117
Tobias Grosserb5563c62017-08-03 13:51:15 +00002118 // Bound the size of the fortran array dimensions.
2119 Context = boundFortranArrayParams(Context, arrays());
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002120
Johannes Doerferta60ad842016-05-10 12:18:22 +00002121 // As all parameters are known add bounds to them.
2122 addParameterBounds();
2123
Tobias Grosser7c3bad52015-05-27 05:16:57 +00002124 for (ScopStmt &Stmt : *this)
2125 Stmt.realignParams();
Johannes Doerfert06445ded2016-06-02 15:07:41 +00002126 // Simplify the schedule according to the context too.
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002127 Schedule = Schedule.gist_domain_params(getContext());
Tobias Grosser8cae72f2011-11-08 15:41:08 +00002128}
2129
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002130static isl::set simplifyAssumptionContext(isl::set AssumptionContext,
2131 const Scop &S) {
Tobias Grossercdbe5c92017-01-06 17:30:34 +00002132 // If we have modeled all blocks in the SCoP that have side effects we can
2133 // simplify the context with the constraints that are needed for anything to
2134 // be executed at all. However, if we have error blocks in the SCoP we already
2135 // assumed some parameter combinations cannot occur and removed them from the
Johannes Doerfertf85ad042015-11-08 20:16:39 +00002136 // domains, thus we cannot use the remaining domain to simplify the
2137 // assumptions.
2138 if (!S.hasErrorBlock()) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002139 auto DomainParameters = S.getDomains().params();
2140 AssumptionContext = AssumptionContext.gist_params(DomainParameters);
Johannes Doerfertf85ad042015-11-08 20:16:39 +00002141 }
2142
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002143 AssumptionContext = AssumptionContext.gist_params(S.getContext());
Johannes Doerfert883f8c12015-09-15 22:52:53 +00002144 return AssumptionContext;
2145}
2146
2147void Scop::simplifyContexts() {
Tobias Grosser5e6813d2014-07-02 17:47:48 +00002148 // The parameter constraints of the iteration domains give us a set of
2149 // constraints that need to hold for all cases where at least a single
2150 // statement iteration is executed in the whole scop. We now simplify the
2151 // assumed context under the assumption that such constraints hold and at
2152 // least a single statement iteration is executed. For cases where no
2153 // statement instances are executed, the assumptions we have taken about
2154 // the executed code do not matter and can be changed.
2155 //
2156 // WARNING: This only holds if the assumptions we have taken do not reduce
2157 // the set of statement instances that are executed. Otherwise we
2158 // may run into a case where the iteration domains suggest that
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002159 // for a certain set of parameter constraints no code is executed,
Tobias Grosser5e6813d2014-07-02 17:47:48 +00002160 // but in the original program some computation would have been
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002161 // performed. In such a case, modifying the run-time conditions and
2162 // possibly influencing the run-time check may cause certain scops
Tobias Grosser5e6813d2014-07-02 17:47:48 +00002163 // to not be executed.
2164 //
2165 // Example:
2166 //
2167 // When delinearizing the following code:
2168 //
2169 // for (long i = 0; i < 100; i++)
2170 // for (long j = 0; j < m; j++)
2171 // A[i+p][j] = 1.0;
2172 //
2173 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002174 // otherwise we would access out of bound data. Now, knowing that code is
Tobias Grosser5e6813d2014-07-02 17:47:48 +00002175 // only executed for the case m >= 0, it is sufficient to assume p >= 0.
Johannes Doerfert883f8c12015-09-15 22:52:53 +00002176 AssumedContext = simplifyAssumptionContext(AssumedContext, *this);
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002177 InvalidContext = InvalidContext.align_params(getParamSpace());
Tobias Grosser5e6813d2014-07-02 17:47:48 +00002178}
2179
Tobias Grosserc80d6972016-09-02 06:33:33 +00002180/// Helper to treat non-affine regions and basic blocks the same.
Johannes Doerfert96425c22015-08-30 21:13:53 +00002181///
2182///{
2183
Tobias Grosserc80d6972016-09-02 06:33:33 +00002184/// Return the block that is the representing block for @p RN.
Johannes Doerfert96425c22015-08-30 21:13:53 +00002185static inline BasicBlock *getRegionNodeBasicBlock(RegionNode *RN) {
2186 return RN->isSubRegion() ? RN->getNodeAs<Region>()->getEntry()
2187 : RN->getNodeAs<BasicBlock>();
2188}
2189
Tobias Grosserc80d6972016-09-02 06:33:33 +00002190/// Return the @p idx'th block that is executed after @p RN.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002191static inline BasicBlock *
Chandler Carruthe303c872018-10-15 10:42:50 +00002192getRegionNodeSuccessor(RegionNode *RN, Instruction *TI, unsigned idx) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002193 if (RN->isSubRegion()) {
2194 assert(idx == 0);
2195 return RN->getNodeAs<Region>()->getExit();
2196 }
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002197 return TI->getSuccessor(idx);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002198}
2199
Tobias Grosserc80d6972016-09-02 06:33:33 +00002200/// Return the smallest loop surrounding @p RN.
Johannes Doerfert96425c22015-08-30 21:13:53 +00002201static inline Loop *getRegionNodeLoop(RegionNode *RN, LoopInfo &LI) {
Tobias Grosserce69e7b2017-03-07 16:17:55 +00002202 if (!RN->isSubRegion()) {
2203 BasicBlock *BB = RN->getNodeAs<BasicBlock>();
2204 Loop *L = LI.getLoopFor(BB);
2205
2206 // Unreachable statements are not considered to belong to a LLVM loop, as
2207 // they are not part of an actual loop in the control flow graph.
2208 // Nevertheless, we handle certain unreachable statements that are common
2209 // when modeling run-time bounds checks as being part of the loop to be
2210 // able to model them and to later eliminate the run-time bounds checks.
2211 //
2212 // Specifically, for basic blocks that terminate in an unreachable and
Michael Krusea6d48f52017-06-08 12:06:15 +00002213 // where the immediate predecessor is part of a loop, we assume these
Tobias Grosserce69e7b2017-03-07 16:17:55 +00002214 // basic blocks belong to the loop the predecessor belongs to. This
2215 // allows us to model the following code.
2216 //
2217 // for (i = 0; i < N; i++) {
2218 // if (i > 1024)
2219 // abort(); <- this abort might be translated to an
2220 // unreachable
2221 //
2222 // A[i] = ...
2223 // }
2224 if (!L && isa<UnreachableInst>(BB->getTerminator()) && BB->getPrevNode())
2225 L = LI.getLoopFor(BB->getPrevNode());
2226 return L;
2227 }
Johannes Doerfert96425c22015-08-30 21:13:53 +00002228
2229 Region *NonAffineSubRegion = RN->getNodeAs<Region>();
2230 Loop *L = LI.getLoopFor(NonAffineSubRegion->getEntry());
2231 while (L && NonAffineSubRegion->contains(L))
2232 L = L->getParentLoop();
2233 return L;
2234}
2235
Tobias Grosserce69e7b2017-03-07 16:17:55 +00002236/// Get the number of blocks in @p L.
2237///
2238/// The number of blocks in a loop are the number of basic blocks actually
2239/// belonging to the loop, as well as all single basic blocks that the loop
2240/// exits to and which terminate in an unreachable instruction. We do not
2241/// allow such basic blocks in the exit of a scop, hence they belong to the
2242/// scop and represent run-time conditions which we want to model and
2243/// subsequently speculate away.
2244///
2245/// @see getRegionNodeLoop for additional details.
Reid Klecknerdf2b2832017-06-19 17:44:02 +00002246unsigned getNumBlocksInLoop(Loop *L) {
2247 unsigned NumBlocks = L->getNumBlocks();
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00002248 SmallVector<BasicBlock *, 4> ExitBlocks;
Tobias Grosserce69e7b2017-03-07 16:17:55 +00002249 L->getExitBlocks(ExitBlocks);
2250
2251 for (auto ExitBlock : ExitBlocks) {
2252 if (isa<UnreachableInst>(ExitBlock->getTerminator()))
2253 NumBlocks++;
2254 }
2255 return NumBlocks;
2256}
2257
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002258static inline unsigned getNumBlocksInRegionNode(RegionNode *RN) {
2259 if (!RN->isSubRegion())
2260 return 1;
2261
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002262 Region *R = RN->getNodeAs<Region>();
Tobias Grosser0dd4a9a2016-02-01 01:55:08 +00002263 return std::distance(R->block_begin(), R->block_end());
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002264}
2265
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002266static bool containsErrorBlock(RegionNode *RN, const Region &R, LoopInfo &LI,
2267 const DominatorTree &DT) {
Johannes Doerfertf5673802015-10-01 23:48:18 +00002268 if (!RN->isSubRegion())
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002269 return isErrorBlock(*RN->getNodeAs<BasicBlock>(), R, LI, DT);
Johannes Doerfertf5673802015-10-01 23:48:18 +00002270 for (BasicBlock *BB : RN->getNodeAs<Region>()->blocks())
Johannes Doerfert08d90a32015-10-07 20:32:43 +00002271 if (isErrorBlock(*BB, R, LI, DT))
Johannes Doerfertf5673802015-10-01 23:48:18 +00002272 return true;
2273 return false;
2274}
2275
Johannes Doerfert96425c22015-08-30 21:13:53 +00002276///}
2277
Tobias Grosser61bd3a42017-08-06 21:42:38 +00002278isl::set Scop::getDomainConditions(const ScopStmt *Stmt) const {
Michael Kruse375cb5f2016-02-24 22:08:24 +00002279 return getDomainConditions(Stmt->getEntryBlock());
Johannes Doerfertcef616f2015-09-15 22:49:04 +00002280}
2281
Tobias Grosser61bd3a42017-08-06 21:42:38 +00002282isl::set Scop::getDomainConditions(BasicBlock *BB) const {
Johannes Doerfert41cda152016-04-08 10:32:26 +00002283 auto DIt = DomainMap.find(BB);
2284 if (DIt != DomainMap.end())
Tobias Grosser61bd3a42017-08-06 21:42:38 +00002285 return DIt->getSecond();
Johannes Doerfert41cda152016-04-08 10:32:26 +00002286
2287 auto &RI = *R.getRegionInfo();
2288 auto *BBR = RI.getRegionFor(BB);
2289 while (BBR->getEntry() == BB)
2290 BBR = BBR->getParent();
2291 return getDomainConditions(BBR->getEntry());
Johannes Doerfert96425c22015-08-30 21:13:53 +00002292}
2293
Tobias Grosser13acbb92017-07-15 09:01:31 +00002294bool Scop::buildDomains(Region *R, DominatorTree &DT, LoopInfo &LI,
2295 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfertffd222f2016-05-19 12:34:57 +00002296 bool IsOnlyNonAffineRegion = isNonAffineSubRegion(R);
Johannes Doerfertf08bd002015-08-31 13:56:32 +00002297 auto *EntryBB = R->getEntry();
Johannes Doerfert432658d2016-01-26 11:01:41 +00002298 auto *L = IsOnlyNonAffineRegion ? nullptr : LI.getLoopFor(EntryBB);
2299 int LD = getRelativeLoopDepth(L);
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002300 auto *S = isl_set_universe(isl_space_set_alloc(getIslCtx().get(), 0, LD + 1));
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002301
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002302 while (LD-- >= 0) {
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002303 L = L->getParentLoop();
2304 }
2305
Tobias Grosser13acbb92017-07-15 09:01:31 +00002306 InvalidDomainMap[EntryBB] = isl::manage(isl_set_empty(isl_set_get_space(S)));
Tobias Grosser325204a32017-07-15 12:41:32 +00002307 DomainMap[EntryBB] = isl::manage(S);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002308
Johannes Doerfert432658d2016-01-26 11:01:41 +00002309 if (IsOnlyNonAffineRegion)
Johannes Doerfert26404542016-05-10 12:19:47 +00002310 return !containsErrorBlock(R->getNode(), *R, LI, DT);
Johannes Doerfert40fa56f2015-09-14 11:15:07 +00002311
Michael Kruse476f8552017-06-29 12:47:41 +00002312 if (!buildDomainsWithBranchConstraints(R, DT, LI, InvalidDomainMap))
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002313 return false;
2314
Michael Kruse476f8552017-06-29 12:47:41 +00002315 if (!propagateDomainConstraints(R, DT, LI, InvalidDomainMap))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002316 return false;
Tobias Grosser9737c7b2015-11-22 11:06:51 +00002317
2318 // Error blocks and blocks dominated by them have been assumed to never be
2319 // executed. Representing them in the Scop does not add any value. In fact,
2320 // it is likely to cause issues during construction of the ScopStmts. The
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002321 // contents of error blocks have not been verified to be expressible and
Tobias Grosser9737c7b2015-11-22 11:06:51 +00002322 // will cause problems when building up a ScopStmt for them.
2323 // Furthermore, basic blocks dominated by error blocks may reference
2324 // instructions in the error block which, if the error block is not modeled,
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002325 // can themselves not be constructed properly. To this end we will replace
2326 // the domains of error blocks and those only reachable via error blocks
2327 // with an empty set. Additionally, we will record for each block under which
Johannes Doerfert7c013572016-04-12 09:57:34 +00002328 // parameter combination it would be reached via an error block in its
Johannes Doerferta3519512016-04-23 13:02:23 +00002329 // InvalidDomain. This information is needed during load hoisting.
Michael Kruse476f8552017-06-29 12:47:41 +00002330 if (!propagateInvalidStmtDomains(R, DT, LI, InvalidDomainMap))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002331 return false;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002332
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002333 return true;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002334}
2335
Tobias Grosserc80d6972016-09-02 06:33:33 +00002336/// Adjust the dimensions of @p Dom that was constructed for @p OldL
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002337/// to be compatible to domains constructed for loop @p NewL.
2338///
2339/// This function assumes @p NewL and @p OldL are equal or there is a CFG
2340/// edge from @p OldL to @p NewL.
Tobias Grosser67dc08b2018-06-18 13:01:52 +00002341static isl::set adjustDomainDimensions(Scop &S, isl::set Dom, Loop *OldL,
2342 Loop *NewL) {
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002343 // If the loops are the same there is nothing to do.
2344 if (NewL == OldL)
2345 return Dom;
2346
2347 int OldDepth = S.getRelativeLoopDepth(OldL);
2348 int NewDepth = S.getRelativeLoopDepth(NewL);
2349 // If both loops are non-affine loops there is nothing to do.
2350 if (OldDepth == -1 && NewDepth == -1)
2351 return Dom;
2352
2353 // Distinguish three cases:
2354 // 1) The depth is the same but the loops are not.
2355 // => One loop was left one was entered.
2356 // 2) The depth increased from OldL to NewL.
2357 // => One loop was entered, none was left.
2358 // 3) The depth decreased from OldL to NewL.
2359 // => Loops were left were difference of the depths defines how many.
2360 if (OldDepth == NewDepth) {
2361 assert(OldL->getParentLoop() == NewL->getParentLoop());
Tobias Grosser9b29af92018-06-18 12:49:47 +00002362 Dom = Dom.project_out(isl::dim::set, NewDepth, 1);
2363 Dom = Dom.add_dims(isl::dim::set, 1);
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002364 } else if (OldDepth < NewDepth) {
2365 assert(OldDepth + 1 == NewDepth);
2366 auto &R = S.getRegion();
2367 (void)R;
2368 assert(NewL->getParentLoop() == OldL ||
2369 ((!OldL || !R.contains(OldL)) && R.contains(NewL)));
Tobias Grosser9b29af92018-06-18 12:49:47 +00002370 Dom = Dom.add_dims(isl::dim::set, 1);
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002371 } else {
2372 assert(OldDepth > NewDepth);
2373 int Diff = OldDepth - NewDepth;
Tobias Grosser9b29af92018-06-18 12:49:47 +00002374 int NumDim = Dom.n_dim();
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002375 assert(NumDim >= Diff);
Tobias Grosser9b29af92018-06-18 12:49:47 +00002376 Dom = Dom.project_out(isl::dim::set, NumDim - Diff, Diff);
Johannes Doerferta07f0ac2016-04-04 07:50:40 +00002377 }
2378
2379 return Dom;
2380}
Johannes Doerfert642594a2016-04-04 07:57:39 +00002381
Michael Kruse476f8552017-06-29 12:47:41 +00002382bool Scop::propagateInvalidStmtDomains(
2383 Region *R, DominatorTree &DT, LoopInfo &LI,
Tobias Grosser13acbb92017-07-15 09:01:31 +00002384 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002385 ReversePostOrderTraversal<Region *> RTraversal(R);
2386 for (auto *RN : RTraversal) {
2387
2388 // Recurse for affine subregions but go on for basic blocks and non-affine
2389 // subregions.
2390 if (RN->isSubRegion()) {
2391 Region *SubRegion = RN->getNodeAs<Region>();
Johannes Doerfertffd222f2016-05-19 12:34:57 +00002392 if (!isNonAffineSubRegion(SubRegion)) {
Michael Kruse476f8552017-06-29 12:47:41 +00002393 propagateInvalidStmtDomains(SubRegion, DT, LI, InvalidDomainMap);
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002394 continue;
2395 }
2396 }
2397
2398 bool ContainsErrorBlock = containsErrorBlock(RN, getRegion(), LI, DT);
2399 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Tobias Grosser325204a32017-07-15 12:41:32 +00002400 isl::set &Domain = DomainMap[BB];
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002401 assert(Domain && "Cannot propagate a nullptr");
2402
Tobias Grosser325204a32017-07-15 12:41:32 +00002403 isl::set InvalidDomain = InvalidDomainMap[BB];
Michael Kruse476f8552017-06-29 12:47:41 +00002404
Tobias Grosser325204a32017-07-15 12:41:32 +00002405 bool IsInvalidBlock = ContainsErrorBlock || Domain.is_subset(InvalidDomain);
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002406
Johannes Doerferta3519512016-04-23 13:02:23 +00002407 if (!IsInvalidBlock) {
Tobias Grosser325204a32017-07-15 12:41:32 +00002408 InvalidDomain = InvalidDomain.intersect(Domain);
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002409 } else {
Johannes Doerferta3519512016-04-23 13:02:23 +00002410 InvalidDomain = Domain;
Tobias Grosser325204a32017-07-15 12:41:32 +00002411 isl::set DomPar = Domain.params();
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002412 recordAssumption(ERRORBLOCK, DomPar, BB->getTerminator()->getDebugLoc(),
2413 AS_RESTRICTION);
Michael Kruse842bdd02018-08-01 22:28:32 +00002414 Domain = isl::set::empty(Domain.get_space());
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002415 }
2416
Tobias Grosser325204a32017-07-15 12:41:32 +00002417 if (InvalidDomain.is_empty()) {
2418 InvalidDomainMap[BB] = InvalidDomain;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002419 continue;
Johannes Doerfert7c013572016-04-12 09:57:34 +00002420 }
2421
Johannes Doerferta3519512016-04-23 13:02:23 +00002422 auto *BBLoop = getRegionNodeLoop(RN, LI);
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002423 auto *TI = BB->getTerminator();
2424 unsigned NumSuccs = RN->isSubRegion() ? 1 : TI->getNumSuccessors();
2425 for (unsigned u = 0; u < NumSuccs; u++) {
2426 auto *SuccBB = getRegionNodeSuccessor(RN, TI, u);
Johannes Doerfert7c013572016-04-12 09:57:34 +00002427
2428 // Skip successors outside the SCoP.
Michael Kruse476f8552017-06-29 12:47:41 +00002429 if (!contains(SuccBB))
Johannes Doerfert7c013572016-04-12 09:57:34 +00002430 continue;
2431
Johannes Doerferte4459a22016-04-25 13:34:50 +00002432 // Skip backedges.
2433 if (DT.dominates(SuccBB, BB))
2434 continue;
2435
Michael Kruse476f8552017-06-29 12:47:41 +00002436 Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops());
2437
Tobias Grosser67dc08b2018-06-18 13:01:52 +00002438 auto AdjustedInvalidDomain =
2439 adjustDomainDimensions(*this, InvalidDomain, BBLoop, SuccBBLoop);
Michael Kruse476f8552017-06-29 12:47:41 +00002440
Philip Pfaffe9375d572018-05-16 14:05:03 +00002441 isl::set SuccInvalidDomain = InvalidDomainMap[SuccBB];
2442 SuccInvalidDomain = SuccInvalidDomain.unite(AdjustedInvalidDomain);
2443 SuccInvalidDomain = SuccInvalidDomain.coalesce();
2444 unsigned NumConjucts = SuccInvalidDomain.n_basic_set();
Michael Kruse476f8552017-06-29 12:47:41 +00002445
Philip Pfaffe9375d572018-05-16 14:05:03 +00002446 InvalidDomainMap[SuccBB] = SuccInvalidDomain;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002447
Michael Krusebc150122016-05-02 12:25:18 +00002448 // Check if the maximal number of domain disjunctions was reached.
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002449 // In case this happens we will bail.
Tobias Grosser90411a92017-02-16 19:11:33 +00002450 if (NumConjucts < MaxDisjunctsInDomain)
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002451 continue;
2452
Tobias Grosserf44f0052017-07-09 15:47:17 +00002453 InvalidDomainMap.erase(BB);
Eli Friedmane737fc12017-07-17 23:58:33 +00002454 invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent());
Johannes Doerfert297c7202016-05-10 13:06:42 +00002455 return false;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002456 }
Johannes Doerferta3519512016-04-23 13:02:23 +00002457
Tobias Grosser325204a32017-07-15 12:41:32 +00002458 InvalidDomainMap[BB] = InvalidDomain;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002459 }
Johannes Doerfert297c7202016-05-10 13:06:42 +00002460
2461 return true;
Johannes Doerfert3ef78d62016-04-08 10:30:09 +00002462}
2463
Johannes Doerfert642594a2016-04-04 07:57:39 +00002464void Scop::propagateDomainConstraintsToRegionExit(
2465 BasicBlock *BB, Loop *BBLoop,
Michael Kruse476f8552017-06-29 12:47:41 +00002466 SmallPtrSetImpl<BasicBlock *> &FinishedExitBlocks, LoopInfo &LI,
Tobias Grosser13acbb92017-07-15 09:01:31 +00002467 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfert642594a2016-04-04 07:57:39 +00002468 // Check if the block @p BB is the entry of a region. If so we propagate it's
2469 // domain to the exit block of the region. Otherwise we are done.
2470 auto *RI = R.getRegionInfo();
2471 auto *BBReg = RI ? RI->getRegionFor(BB) : nullptr;
2472 auto *ExitBB = BBReg ? BBReg->getExit() : nullptr;
Johannes Doerfert952b5302016-05-23 12:40:48 +00002473 if (!BBReg || BBReg->getEntry() != BB || !contains(ExitBB))
Johannes Doerfert642594a2016-04-04 07:57:39 +00002474 return;
2475
Johannes Doerfert642594a2016-04-04 07:57:39 +00002476 // Do not propagate the domain if there is a loop backedge inside the region
Tobias Grossercdbe5c92017-01-06 17:30:34 +00002477 // that would prevent the exit block from being executed.
Johannes Doerfert642594a2016-04-04 07:57:39 +00002478 auto *L = BBLoop;
Johannes Doerfert952b5302016-05-23 12:40:48 +00002479 while (L && contains(L)) {
Johannes Doerfert642594a2016-04-04 07:57:39 +00002480 SmallVector<BasicBlock *, 4> LatchBBs;
2481 BBLoop->getLoopLatches(LatchBBs);
2482 for (auto *LatchBB : LatchBBs)
2483 if (BB != LatchBB && BBReg->contains(LatchBB))
2484 return;
2485 L = L->getParentLoop();
2486 }
2487
Tobias Grosser325204a32017-07-15 12:41:32 +00002488 isl::set Domain = DomainMap[BB];
Johannes Doerfert642594a2016-04-04 07:57:39 +00002489 assert(Domain && "Cannot propagate a nullptr");
2490
Michael Kruse476f8552017-06-29 12:47:41 +00002491 Loop *ExitBBLoop = getFirstNonBoxedLoopFor(ExitBB, LI, getBoxedLoops());
Johannes Doerfert642594a2016-04-04 07:57:39 +00002492
2493 // Since the dimensions of @p BB and @p ExitBB might be different we have to
2494 // adjust the domain before we can propagate it.
Tobias Grosser67dc08b2018-06-18 13:01:52 +00002495 isl::set AdjustedDomain =
2496 adjustDomainDimensions(*this, Domain, BBLoop, ExitBBLoop);
Tobias Grosser325204a32017-07-15 12:41:32 +00002497 isl::set &ExitDomain = DomainMap[ExitBB];
Johannes Doerfert642594a2016-04-04 07:57:39 +00002498
2499 // If the exit domain is not yet created we set it otherwise we "add" the
2500 // current domain.
Tobias Grosser325204a32017-07-15 12:41:32 +00002501 ExitDomain = ExitDomain ? AdjustedDomain.unite(ExitDomain) : AdjustedDomain;
Johannes Doerfert642594a2016-04-04 07:57:39 +00002502
Johannes Doerferta3519512016-04-23 13:02:23 +00002503 // Initialize the invalid domain.
Tobias Grosser325204a32017-07-15 12:41:32 +00002504 InvalidDomainMap[ExitBB] = ExitDomain.empty(ExitDomain.get_space());
Johannes Doerferta3519512016-04-23 13:02:23 +00002505
Johannes Doerfert642594a2016-04-04 07:57:39 +00002506 FinishedExitBlocks.insert(ExitBB);
2507}
2508
Michael Kruse476f8552017-06-29 12:47:41 +00002509bool Scop::buildDomainsWithBranchConstraints(
2510 Region *R, DominatorTree &DT, LoopInfo &LI,
Tobias Grosser13acbb92017-07-15 09:01:31 +00002511 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002512 // To create the domain for each block in R we iterate over all blocks and
2513 // subregions in R and propagate the conditions under which the current region
2514 // element is executed. To this end we iterate in reverse post order over R as
2515 // it ensures that we first visit all predecessors of a region node (either a
2516 // basic block or a subregion) before we visit the region node itself.
2517 // Initially, only the domain for the SCoP region entry block is set and from
2518 // there we propagate the current domain to all successors, however we add the
2519 // condition that the successor is actually executed next.
2520 // As we are only interested in non-loop carried constraints here we can
2521 // simply skip loop back edges.
2522
Johannes Doerfert642594a2016-04-04 07:57:39 +00002523 SmallPtrSet<BasicBlock *, 8> FinishedExitBlocks;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002524 ReversePostOrderTraversal<Region *> RTraversal(R);
2525 for (auto *RN : RTraversal) {
Johannes Doerfert96425c22015-08-30 21:13:53 +00002526 // Recurse for affine subregions but go on for basic blocks and non-affine
2527 // subregions.
2528 if (RN->isSubRegion()) {
2529 Region *SubRegion = RN->getNodeAs<Region>();
Johannes Doerfertffd222f2016-05-19 12:34:57 +00002530 if (!isNonAffineSubRegion(SubRegion)) {
Michael Kruse476f8552017-06-29 12:47:41 +00002531 if (!buildDomainsWithBranchConstraints(SubRegion, DT, LI,
2532 InvalidDomainMap))
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002533 return false;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002534 continue;
2535 }
2536 }
2537
Tobias Grosserb76cd3c2015-11-11 08:42:20 +00002538 if (containsErrorBlock(RN, getRegion(), LI, DT))
Johannes Doerfertf85ad042015-11-08 20:16:39 +00002539 HasErrorBlock = true;
Johannes Doerfertf5673802015-10-01 23:48:18 +00002540
Johannes Doerfert96425c22015-08-30 21:13:53 +00002541 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Chandler Carruthe303c872018-10-15 10:42:50 +00002542 Instruction *TI = BB->getTerminator();
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002543
Tobias Grosserb76cd3c2015-11-11 08:42:20 +00002544 if (isa<UnreachableInst>(TI))
2545 continue;
2546
Tobias Grosser325204a32017-07-15 12:41:32 +00002547 isl::set Domain = DomainMap.lookup(BB);
Tobias Grosser4fb9e512016-02-27 06:59:30 +00002548 if (!Domain)
Johannes Doerfert90db75e2015-09-10 17:51:27 +00002549 continue;
Tobias Grosser325204a32017-07-15 12:41:32 +00002550 MaxLoopDepth = std::max(MaxLoopDepth, isl_set_n_dim(Domain.get()));
Johannes Doerfert96425c22015-08-30 21:13:53 +00002551
Johannes Doerfert642594a2016-04-04 07:57:39 +00002552 auto *BBLoop = getRegionNodeLoop(RN, LI);
2553 // Propagate the domain from BB directly to blocks that have a superset
2554 // domain, at the moment only region exit nodes of regions that start in BB.
Michael Kruse476f8552017-06-29 12:47:41 +00002555 propagateDomainConstraintsToRegionExit(BB, BBLoop, FinishedExitBlocks, LI,
2556 InvalidDomainMap);
Johannes Doerfert642594a2016-04-04 07:57:39 +00002557
2558 // If all successors of BB have been set a domain through the propagation
2559 // above we do not need to build condition sets but can just skip this
2560 // block. However, it is important to note that this is a local property
2561 // with regards to the region @p R. To this end FinishedExitBlocks is a
2562 // local variable.
2563 auto IsFinishedRegionExit = [&FinishedExitBlocks](BasicBlock *SuccBB) {
2564 return FinishedExitBlocks.count(SuccBB);
2565 };
2566 if (std::all_of(succ_begin(BB), succ_end(BB), IsFinishedRegionExit))
2567 continue;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002568
2569 // Build the condition sets for the successor nodes of the current region
2570 // node. If it is a non-affine subregion we will always execute the single
2571 // exit node, hence the single entry node domain is the condition set. For
2572 // basic blocks we use the helper function buildConditionSets.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002573 SmallVector<isl_set *, 8> ConditionSets;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002574 if (RN->isSubRegion())
Tobias Grosser325204a32017-07-15 12:41:32 +00002575 ConditionSets.push_back(Domain.copy());
2576 else if (!buildConditionSets(*this, BB, TI, BBLoop, Domain.get(),
Michael Kruse476f8552017-06-29 12:47:41 +00002577 InvalidDomainMap, ConditionSets))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002578 return false;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002579
2580 // Now iterate over the successors and set their initial domain based on
2581 // their condition set. We skip back edges here and have to be careful when
2582 // we leave a loop not to keep constraints over a dimension that doesn't
2583 // exist anymore.
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002584 assert(RN->isSubRegion() || TI->getNumSuccessors() == ConditionSets.size());
Johannes Doerfert96425c22015-08-30 21:13:53 +00002585 for (unsigned u = 0, e = ConditionSets.size(); u < e; u++) {
Tobias Grosser325204a32017-07-15 12:41:32 +00002586 isl::set CondSet = isl::manage(ConditionSets[u]);
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002587 BasicBlock *SuccBB = getRegionNodeSuccessor(RN, TI, u);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002588
Johannes Doerfert535de032016-04-19 14:49:05 +00002589 // Skip blocks outside the region.
Tobias Grosser325204a32017-07-15 12:41:32 +00002590 if (!contains(SuccBB))
Johannes Doerfert535de032016-04-19 14:49:05 +00002591 continue;
Johannes Doerfert535de032016-04-19 14:49:05 +00002592
Johannes Doerfert642594a2016-04-04 07:57:39 +00002593 // If we propagate the domain of some block to "SuccBB" we do not have to
2594 // adjust the domain.
Tobias Grosser325204a32017-07-15 12:41:32 +00002595 if (FinishedExitBlocks.count(SuccBB))
Johannes Doerfert642594a2016-04-04 07:57:39 +00002596 continue;
Johannes Doerfert642594a2016-04-04 07:57:39 +00002597
Johannes Doerfert96425c22015-08-30 21:13:53 +00002598 // Skip back edges.
Tobias Grosser325204a32017-07-15 12:41:32 +00002599 if (DT.dominates(SuccBB, BB))
Johannes Doerfert96425c22015-08-30 21:13:53 +00002600 continue;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002601
Michael Kruse476f8552017-06-29 12:47:41 +00002602 Loop *SuccBBLoop = getFirstNonBoxedLoopFor(SuccBB, LI, getBoxedLoops());
2603
Tobias Grosser9b29af92018-06-18 12:49:47 +00002604 CondSet = adjustDomainDimensions(*this, CondSet, BBLoop, SuccBBLoop);
Johannes Doerfert96425c22015-08-30 21:13:53 +00002605
2606 // Set the domain for the successor or merge it with an existing domain in
2607 // case there are multiple paths (without loop back edges) to the
2608 // successor block.
Tobias Grosser325204a32017-07-15 12:41:32 +00002609 isl::set &SuccDomain = DomainMap[SuccBB];
Tobias Grosser5a8c0522016-03-22 22:05:32 +00002610
Johannes Doerferta3519512016-04-23 13:02:23 +00002611 if (SuccDomain) {
Tobias Grosser325204a32017-07-15 12:41:32 +00002612 SuccDomain = SuccDomain.unite(CondSet).coalesce();
Johannes Doerferta3519512016-04-23 13:02:23 +00002613 } else {
2614 // Initialize the invalid domain.
Tobias Grosser325204a32017-07-15 12:41:32 +00002615 InvalidDomainMap[SuccBB] = CondSet.empty(CondSet.get_space());
Johannes Doerferta3519512016-04-23 13:02:23 +00002616 SuccDomain = CondSet;
2617 }
Johannes Doerfert96425c22015-08-30 21:13:53 +00002618
Tobias Grosser325204a32017-07-15 12:41:32 +00002619 SuccDomain = SuccDomain.detect_equalities();
Tobias Grosser6d459c52017-05-23 04:26:28 +00002620
Michael Krusebc150122016-05-02 12:25:18 +00002621 // Check if the maximal number of domain disjunctions was reached.
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002622 // In case this happens we will clean up and bail.
Philip Pfaffe9375d572018-05-16 14:05:03 +00002623 if (SuccDomain.n_basic_set() < MaxDisjunctsInDomain)
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002624 continue;
2625
2626 invalidate(COMPLEXITY, DebugLoc());
2627 while (++u < ConditionSets.size())
2628 isl_set_free(ConditionSets[u]);
2629 return false;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002630 }
2631 }
Johannes Doerfert5fb9b212016-03-29 20:02:05 +00002632
2633 return true;
Johannes Doerfert96425c22015-08-30 21:13:53 +00002634}
2635
Tobias Grosser2f3041f2017-08-06 17:31:38 +00002636isl::set Scop::getPredecessorDomainConstraints(BasicBlock *BB, isl::set Domain,
2637 DominatorTree &DT,
2638 LoopInfo &LI) {
Johannes Doerfert642594a2016-04-04 07:57:39 +00002639 // If @p BB is the ScopEntry we are done
2640 if (R.getEntry() == BB)
Tobias Grosser2f3041f2017-08-06 17:31:38 +00002641 return isl::set::universe(Domain.get_space());
Johannes Doerfert642594a2016-04-04 07:57:39 +00002642
Johannes Doerfert642594a2016-04-04 07:57:39 +00002643 // The region info of this function.
2644 auto &RI = *R.getRegionInfo();
2645
Michael Kruse476f8552017-06-29 12:47:41 +00002646 Loop *BBLoop = getFirstNonBoxedLoopFor(BB, LI, getBoxedLoops());
Johannes Doerfert642594a2016-04-04 07:57:39 +00002647
2648 // A domain to collect all predecessor domains, thus all conditions under
2649 // which the block is executed. To this end we start with the empty domain.
Tobias Grosser2f3041f2017-08-06 17:31:38 +00002650 isl::set PredDom = isl::set::empty(Domain.get_space());
Johannes Doerfert642594a2016-04-04 07:57:39 +00002651
2652 // Set of regions of which the entry block domain has been propagated to BB.
2653 // all predecessors inside any of the regions can be skipped.
2654 SmallSet<Region *, 8> PropagatedRegions;
2655
2656 for (auto *PredBB : predecessors(BB)) {
2657 // Skip backedges.
2658 if (DT.dominates(BB, PredBB))
2659 continue;
2660
2661 // If the predecessor is in a region we used for propagation we can skip it.
2662 auto PredBBInRegion = [PredBB](Region *PR) { return PR->contains(PredBB); };
2663 if (std::any_of(PropagatedRegions.begin(), PropagatedRegions.end(),
2664 PredBBInRegion)) {
2665 continue;
2666 }
2667
2668 // Check if there is a valid region we can use for propagation, thus look
2669 // for a region that contains the predecessor and has @p BB as exit block.
2670 auto *PredR = RI.getRegionFor(PredBB);
2671 while (PredR->getExit() != BB && !PredR->contains(BB))
2672 PredR->getParent();
2673
2674 // If a valid region for propagation was found use the entry of that region
2675 // for propagation, otherwise the PredBB directly.
2676 if (PredR->getExit() == BB) {
2677 PredBB = PredR->getEntry();
2678 PropagatedRegions.insert(PredR);
2679 }
2680
Tobias Grosser9b29af92018-06-18 12:49:47 +00002681 isl::set PredBBDom = getDomainConditions(PredBB);
Michael Kruse476f8552017-06-29 12:47:41 +00002682 Loop *PredBBLoop = getFirstNonBoxedLoopFor(PredBB, LI, getBoxedLoops());
Johannes Doerfert642594a2016-04-04 07:57:39 +00002683 PredBBDom = adjustDomainDimensions(*this, PredBBDom, PredBBLoop, BBLoop);
Tobias Grosser9b29af92018-06-18 12:49:47 +00002684 PredDom = PredDom.unite(PredBBDom);
Johannes Doerfert642594a2016-04-04 07:57:39 +00002685 }
2686
2687 return PredDom;
2688}
2689
Michael Kruse476f8552017-06-29 12:47:41 +00002690bool Scop::propagateDomainConstraints(
2691 Region *R, DominatorTree &DT, LoopInfo &LI,
Tobias Grosser13acbb92017-07-15 09:01:31 +00002692 DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002693 // Iterate over the region R and propagate the domain constrains from the
2694 // predecessors to the current node. In contrast to the
2695 // buildDomainsWithBranchConstraints function, this one will pull the domain
2696 // information from the predecessors instead of pushing it to the successors.
2697 // Additionally, we assume the domains to be already present in the domain
2698 // map here. However, we iterate again in reverse post order so we know all
2699 // predecessors have been visited before a block or non-affine subregion is
2700 // visited.
2701
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002702 ReversePostOrderTraversal<Region *> RTraversal(R);
2703 for (auto *RN : RTraversal) {
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002704 // Recurse for affine subregions but go on for basic blocks and non-affine
2705 // subregions.
2706 if (RN->isSubRegion()) {
2707 Region *SubRegion = RN->getNodeAs<Region>();
Johannes Doerfertffd222f2016-05-19 12:34:57 +00002708 if (!isNonAffineSubRegion(SubRegion)) {
Michael Kruse476f8552017-06-29 12:47:41 +00002709 if (!propagateDomainConstraints(SubRegion, DT, LI, InvalidDomainMap))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002710 return false;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002711 continue;
2712 }
2713 }
2714
2715 BasicBlock *BB = getRegionNodeBasicBlock(RN);
Tobias Grosser325204a32017-07-15 12:41:32 +00002716 isl::set &Domain = DomainMap[BB];
Johannes Doerferta49c5572016-04-05 16:18:53 +00002717 assert(Domain);
Johannes Doerfertf5673802015-10-01 23:48:18 +00002718
Tobias Grosser6deba4e2016-03-30 18:18:31 +00002719 // Under the union of all predecessor conditions we can reach this block.
Tobias Grosser2f3041f2017-08-06 17:31:38 +00002720 isl::set PredDom = getPredecessorDomainConstraints(BB, Domain, DT, LI);
Tobias Grosser325204a32017-07-15 12:41:32 +00002721 Domain = Domain.intersect(PredDom).coalesce();
Tobias Grosserb65ccc42017-08-06 20:11:59 +00002722 Domain = Domain.align_params(getParamSpace());
Tobias Grosser6deba4e2016-03-30 18:18:31 +00002723
Johannes Doerfert642594a2016-04-04 07:57:39 +00002724 Loop *BBLoop = getRegionNodeLoop(RN, LI);
Johannes Doerfert952b5302016-05-23 12:40:48 +00002725 if (BBLoop && BBLoop->getHeader() == BB && contains(BBLoop))
Michael Kruse476f8552017-06-29 12:47:41 +00002726 if (!addLoopBoundsToHeaderDomain(BBLoop, LI, InvalidDomainMap))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002727 return false;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002728 }
Johannes Doerfert297c7202016-05-10 13:06:42 +00002729
2730 return true;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002731}
2732
Tobias Grosserc80d6972016-09-02 06:33:33 +00002733/// Create a map to map from a given iteration to a subsequent iteration.
2734///
2735/// This map maps from SetSpace -> SetSpace where the dimensions @p Dim
2736/// is incremented by one and all other dimensions are equal, e.g.,
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002737/// [i0, i1, i2, i3] -> [i0, i1, i2 + 1, i3]
Tobias Grosserc80d6972016-09-02 06:33:33 +00002738///
2739/// if @p Dim is 2 and @p SetSpace has 4 dimensions.
Tobias Grosser10da5a02018-05-23 18:41:40 +00002740static isl::map createNextIterationMap(isl::space SetSpace, unsigned Dim) {
2741 isl::space MapSpace = SetSpace.map_from_set();
2742 isl::map NextIterationMap = isl::map::universe(MapSpace);
2743 for (unsigned u = 0; u < NextIterationMap.dim(isl::dim::in); u++)
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002744 if (u != Dim)
2745 NextIterationMap =
Tobias Grosser10da5a02018-05-23 18:41:40 +00002746 NextIterationMap.equate(isl::dim::in, u, isl::dim::out, u);
2747 isl::constraint C =
2748 isl::constraint::alloc_equality(isl::local_space(MapSpace));
2749 C = C.set_constant_si(1);
2750 C = C.set_coefficient_si(isl::dim::in, Dim, 1);
2751 C = C.set_coefficient_si(isl::dim::out, Dim, -1);
2752 NextIterationMap = NextIterationMap.add_constraint(C);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002753 return NextIterationMap;
2754}
2755
Michael Kruse476f8552017-06-29 12:47:41 +00002756bool Scop::addLoopBoundsToHeaderDomain(
Tobias Grosser13acbb92017-07-15 09:01:31 +00002757 Loop *L, LoopInfo &LI, DenseMap<BasicBlock *, isl::set> &InvalidDomainMap) {
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002758 int LoopDepth = getRelativeLoopDepth(L);
2759 assert(LoopDepth >= 0 && "Loop in region should have at least depth one");
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002760
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002761 BasicBlock *HeaderBB = L->getHeader();
2762 assert(DomainMap.count(HeaderBB));
Tobias Grosser325204a32017-07-15 12:41:32 +00002763 isl::set &HeaderBBDom = DomainMap[HeaderBB];
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002764
Tobias Grosser10da5a02018-05-23 18:41:40 +00002765 isl::map NextIterationMap =
2766 createNextIterationMap(HeaderBBDom.get_space(), LoopDepth);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002767
Tobias Grosser325204a32017-07-15 12:41:32 +00002768 isl::set UnionBackedgeCondition = HeaderBBDom.empty(HeaderBBDom.get_space());
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002769
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00002770 SmallVector<BasicBlock *, 4> LatchBlocks;
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002771 L->getLoopLatches(LatchBlocks);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002772
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002773 for (BasicBlock *LatchBB : LatchBlocks) {
Johannes Doerfertf5673802015-10-01 23:48:18 +00002774 // If the latch is only reachable via error statements we skip it.
Tobias Grosser325204a32017-07-15 12:41:32 +00002775 isl::set LatchBBDom = DomainMap.lookup(LatchBB);
Johannes Doerfertf5673802015-10-01 23:48:18 +00002776 if (!LatchBBDom)
2777 continue;
2778
Tobias Grosser325204a32017-07-15 12:41:32 +00002779 isl::set BackedgeCondition = nullptr;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002780
Chandler Carruthe303c872018-10-15 10:42:50 +00002781 Instruction *TI = LatchBB->getTerminator();
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002782 BranchInst *BI = dyn_cast<BranchInst>(TI);
Tobias Grosserbbaeda32016-11-10 05:20:29 +00002783 assert(BI && "Only branch instructions allowed in loop latches");
2784
2785 if (BI->isUnconditional())
Tobias Grosser325204a32017-07-15 12:41:32 +00002786 BackedgeCondition = LatchBBDom;
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002787 else {
Johannes Doerfert9a132f32015-09-28 09:33:22 +00002788 SmallVector<isl_set *, 8> ConditionSets;
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002789 int idx = BI->getSuccessor(0) != HeaderBB;
Tobias Grosser325204a32017-07-15 12:41:32 +00002790 if (!buildConditionSets(*this, LatchBB, TI, L, LatchBBDom.get(),
2791 InvalidDomainMap, ConditionSets))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002792 return false;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002793
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002794 // Free the non back edge condition set as we do not need it.
2795 isl_set_free(ConditionSets[1 - idx]);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002796
Tobias Grosser325204a32017-07-15 12:41:32 +00002797 BackedgeCondition = isl::manage(ConditionSets[idx]);
Johannes Doerfert06c57b52015-09-20 15:00:20 +00002798 }
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002799
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002800 int LatchLoopDepth = getRelativeLoopDepth(LI.getLoopFor(LatchBB));
2801 assert(LatchLoopDepth >= LoopDepth);
Tobias Grosser325204a32017-07-15 12:41:32 +00002802 BackedgeCondition = BackedgeCondition.project_out(
2803 isl::dim::set, LoopDepth + 1, LatchLoopDepth - LoopDepth);
2804 UnionBackedgeCondition = UnionBackedgeCondition.unite(BackedgeCondition);
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002805 }
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002806
Tobias Grosser325204a32017-07-15 12:41:32 +00002807 isl::map ForwardMap = ForwardMap.lex_le(HeaderBBDom.get_space());
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002808 for (int i = 0; i < LoopDepth; i++)
Tobias Grosser325204a32017-07-15 12:41:32 +00002809 ForwardMap = ForwardMap.equate(isl::dim::in, i, isl::dim::out, i);
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002810
Tobias Grosser325204a32017-07-15 12:41:32 +00002811 isl::set UnionBackedgeConditionComplement =
2812 UnionBackedgeCondition.complement();
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002813 UnionBackedgeConditionComplement =
Tobias Grosser325204a32017-07-15 12:41:32 +00002814 UnionBackedgeConditionComplement.lower_bound_si(isl::dim::set, LoopDepth,
2815 0);
2816 UnionBackedgeConditionComplement =
2817 UnionBackedgeConditionComplement.apply(ForwardMap);
2818 HeaderBBDom = HeaderBBDom.subtract(UnionBackedgeConditionComplement);
2819 HeaderBBDom = HeaderBBDom.apply(NextIterationMap);
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002820
Tobias Grosser78a84942018-06-01 19:12:00 +00002821 auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
2822 HeaderBBDom = Parts.second;
Johannes Doerfertf2cc86e2015-09-20 16:15:32 +00002823
Johannes Doerfert6a72a2a2015-09-20 16:59:23 +00002824 // Check if there is a <nsw> tagged AddRec for this loop and if so do not add
2825 // the bounded assumptions to the context as they are already implied by the
2826 // <nsw> tag.
Tobias Grosser78a84942018-06-01 19:12:00 +00002827 if (Affinator.hasNSWAddRecForLoop(L))
Johannes Doerfert297c7202016-05-10 13:06:42 +00002828 return true;
Johannes Doerfert6a72a2a2015-09-20 16:59:23 +00002829
Tobias Grosser78a84942018-06-01 19:12:00 +00002830 isl::set UnboundedCtx = Parts.first.params();
Johannes Doerfert3bf6e4122016-04-12 13:27:35 +00002831 recordAssumption(INFINITELOOP, UnboundedCtx,
2832 HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
Johannes Doerfert297c7202016-05-10 13:06:42 +00002833 return true;
Johannes Doerfert5b9ff8b2015-09-10 13:00:06 +00002834}
2835
Tobias Grosserc80d6972016-09-02 06:33:33 +00002836/// Get the smallest loop that contains @p S but is not in @p S.
Johannes Doerfertef744432016-05-23 12:42:38 +00002837static Loop *getLoopSurroundingScop(Scop &S, LoopInfo &LI) {
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002838 // Start with the smallest loop containing the entry and expand that
2839 // loop until it contains all blocks in the region. If there is a loop
2840 // containing all blocks in the region check if it is itself contained
2841 // and if so take the parent loop as it will be the smallest containing
2842 // the region but not contained by it.
Johannes Doerfertef744432016-05-23 12:42:38 +00002843 Loop *L = LI.getLoopFor(S.getEntry());
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002844 while (L) {
2845 bool AllContained = true;
Johannes Doerfertef744432016-05-23 12:42:38 +00002846 for (auto *BB : S.blocks())
Johannes Doerfertdec27df2015-11-21 16:56:13 +00002847 AllContained &= L->contains(BB);
2848 if (AllContained)
2849 break;
2850 L = L->getParentLoop();
2851 }
2852
Johannes Doerfertef744432016-05-23 12:42:38 +00002853 return L ? (S.contains(L) ? L->getParentLoop() : L) : nullptr;
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00002854}
2855
Singapuram Sanjay Srivallabh1abd9ff2017-07-12 16:46:19 +00002856int Scop::NextScopID = 0;
2857
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00002858std::string Scop::CurrentFunc;
Singapuram Sanjay Srivallabh1abd9ff2017-07-12 16:46:19 +00002859
2860int Scop::getNextID(std::string ParentFunc) {
2861 if (ParentFunc != CurrentFunc) {
2862 CurrentFunc = ParentFunc;
2863 NextScopID = 0;
2864 }
2865 return NextScopID++;
2866}
2867
Johannes Doerfertffd222f2016-05-19 12:34:57 +00002868Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
Tobias Grosseree457592017-09-24 09:25:30 +00002869 DominatorTree &DT, ScopDetection::DetectionContext &DC,
2870 OptimizationRemarkEmitter &ORE)
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002871 : IslCtx(isl_ctx_alloc(), isl_ctx_free), SE(&ScalarEvolution), DT(&DT),
Philip Pfaffed477bb92018-05-15 14:53:25 +00002872 R(R), name(None), HasSingleExitEdge(R.getExitingBlock()), DC(DC),
2873 ORE(ORE), Affinator(this, LI),
Singapuram Sanjay Srivallabh1abd9ff2017-07-12 16:46:19 +00002874 ID(getNextID((*R.getEntry()->getParent()).getName().str())) {
Tobias Grosser2937b592016-04-29 11:43:20 +00002875 if (IslOnErrorAbort)
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002876 isl_options_set_on_error(getIslCtx().get(), ISL_ON_ERROR_ABORT);
Tobias Grosserd840fc72016-02-04 13:18:42 +00002877 buildContext();
2878}
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002879
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00002880Scop::~Scop() = default;
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00002881
Tobias Grosserbedef002016-12-02 08:10:56 +00002882void Scop::foldSizeConstantsToRight() {
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002883 isl::union_set Accessed = getAccesses().range();
Tobias Grosserbedef002016-12-02 08:10:56 +00002884
2885 for (auto Array : arrays()) {
2886 if (Array->getNumberOfDimensions() <= 1)
2887 continue;
2888
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002889 isl::space Space = Array->getSpace();
2890 Space = Space.align_params(Accessed.get_space());
Tobias Grosserbedef002016-12-02 08:10:56 +00002891
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002892 if (!Accessed.contains(Space))
Tobias Grosserbedef002016-12-02 08:10:56 +00002893 continue;
Tobias Grosserbedef002016-12-02 08:10:56 +00002894
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002895 isl::set Elements = Accessed.extract_set(Space);
2896 isl::map Transform = isl::map::universe(Array->getSpace().map_from_set());
Tobias Grosserbedef002016-12-02 08:10:56 +00002897
2898 std::vector<int> Int;
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002899 int Dims = Elements.dim(isl::dim::set);
Tobias Grosserbedef002016-12-02 08:10:56 +00002900 for (int i = 0; i < Dims; i++) {
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002901 isl::set DimOnly = isl::set(Elements).project_out(isl::dim::set, 0, i);
2902 DimOnly = DimOnly.project_out(isl::dim::set, 1, Dims - i - 1);
2903 DimOnly = DimOnly.lower_bound_si(isl::dim::set, 0, 0);
Tobias Grosserbedef002016-12-02 08:10:56 +00002904
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002905 isl::basic_set DimHull = DimOnly.affine_hull();
Tobias Grosserbedef002016-12-02 08:10:56 +00002906
2907 if (i == Dims - 1) {
2908 Int.push_back(1);
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002909 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
Tobias Grosserbedef002016-12-02 08:10:56 +00002910 continue;
2911 }
2912
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002913 if (DimHull.dim(isl::dim::div) == 1) {
2914 isl::aff Diff = DimHull.get_div(0);
2915 isl::val Val = Diff.get_denominator_val();
Tobias Grosserbedef002016-12-02 08:10:56 +00002916
2917 int ValInt = 1;
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002918 if (Val.is_int()) {
Eli Friedmana75d53c2018-01-17 21:59:02 +00002919 auto ValAPInt = APIntFromVal(Val);
2920 if (ValAPInt.isSignedIntN(32))
2921 ValInt = ValAPInt.getSExtValue();
2922 } else {
Eli Friedmana75d53c2018-01-17 21:59:02 +00002923 }
Tobias Grosserbedef002016-12-02 08:10:56 +00002924
2925 Int.push_back(ValInt);
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002926 isl::constraint C = isl::constraint::alloc_equality(
2927 isl::local_space(Transform.get_space()));
2928 C = C.set_coefficient_si(isl::dim::out, i, ValInt);
2929 C = C.set_coefficient_si(isl::dim::in, i, -1);
2930 Transform = Transform.add_constraint(C);
Tobias Grosserbedef002016-12-02 08:10:56 +00002931 continue;
2932 }
2933
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002934 isl::basic_set ZeroSet = isl::basic_set(DimHull);
2935 ZeroSet = ZeroSet.fix_si(isl::dim::set, 0, 0);
Tobias Grosserbedef002016-12-02 08:10:56 +00002936
2937 int ValInt = 1;
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002938 if (ZeroSet.is_equal(DimHull)) {
Tobias Grosserbedef002016-12-02 08:10:56 +00002939 ValInt = 0;
2940 }
2941
2942 Int.push_back(ValInt);
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002943 Transform = Transform.equate(isl::dim::in, i, isl::dim::out, i);
Tobias Grosserbedef002016-12-02 08:10:56 +00002944 }
2945
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002946 isl::set MappedElements = isl::map(Transform).domain();
2947 if (!Elements.is_subset(MappedElements))
Tobias Grosserbedef002016-12-02 08:10:56 +00002948 continue;
Tobias Grosserbedef002016-12-02 08:10:56 +00002949
2950 bool CanFold = true;
Tobias Grosserbedef002016-12-02 08:10:56 +00002951 if (Int[0] <= 1)
2952 CanFold = false;
2953
2954 unsigned NumDims = Array->getNumberOfDimensions();
2955 for (unsigned i = 1; i < NumDims - 1; i++)
2956 if (Int[0] != Int[i] && Int[i])
2957 CanFold = false;
2958
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002959 if (!CanFold)
Tobias Grosserbedef002016-12-02 08:10:56 +00002960 continue;
Tobias Grosserbedef002016-12-02 08:10:56 +00002961
Tobias Grosserbedef002016-12-02 08:10:56 +00002962 for (auto &Access : AccessFunctions)
2963 if (Access->getScopArrayInfo() == Array)
Tobias Grosser4aab4ec2018-07-05 15:23:28 +00002964 Access->setAccessRelation(
2965 Access->getAccessRelation().apply_range(Transform));
Tobias Grosserbedef002016-12-02 08:10:56 +00002966
2967 std::vector<const SCEV *> Sizes;
2968 for (unsigned i = 0; i < NumDims; i++) {
2969 auto Size = Array->getDimensionSize(i);
2970
2971 if (i == NumDims - 1)
2972 Size = SE->getMulExpr(Size, SE->getConstant(Size->getType(), Int[0]));
2973 Sizes.push_back(Size);
2974 }
2975
2976 Array->updateSizes(Sizes, false /* CheckConsistency */);
Tobias Grosserbedef002016-12-02 08:10:56 +00002977 }
Tobias Grosserbedef002016-12-02 08:10:56 +00002978}
2979
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00002980void Scop::markFortranArrays() {
2981 for (ScopStmt &Stmt : Stmts) {
2982 for (MemoryAccess *MemAcc : Stmt) {
2983 Value *FAD = MemAcc->getFortranArrayDescriptor();
2984 if (!FAD)
2985 continue;
2986
2987 // TODO: const_cast-ing to edit
2988 ScopArrayInfo *SAI =
2989 const_cast<ScopArrayInfo *>(MemAcc->getLatestScopArrayInfo());
2990 assert(SAI && "memory access into a Fortran array does not "
2991 "have an associated ScopArrayInfo");
2992 SAI->applyAndSetFAD(FAD);
2993 }
2994 }
2995}
2996
Tobias Grosser491b7992016-12-02 05:21:22 +00002997void Scop::finalizeAccesses() {
2998 updateAccessDimensionality();
Tobias Grosserbedef002016-12-02 08:10:56 +00002999 foldSizeConstantsToRight();
Tobias Grosser491b7992016-12-02 05:21:22 +00003000 foldAccessRelations();
3001 assumeNoOutOfBounds();
Siddharth Bhatb7f68b82017-05-19 15:07:45 +00003002 markFortranArrays();
Tobias Grosser491b7992016-12-02 05:21:22 +00003003}
3004
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003005void Scop::updateAccessDimensionality() {
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +00003006 // Check all array accesses for each base pointer and find a (virtual) element
3007 // size for the base pointer that divides all access functions.
Tobias Grosser9c7d1812017-02-09 23:24:54 +00003008 for (ScopStmt &Stmt : *this)
3009 for (MemoryAccess *Access : Stmt) {
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +00003010 if (!Access->isArrayKind())
3011 continue;
Tobias Grosser9c7d1812017-02-09 23:24:54 +00003012 ScopArrayInfo *Array =
Tobias Grossere24b7b92017-02-09 23:24:57 +00003013 const_cast<ScopArrayInfo *>(Access->getScopArrayInfo());
3014
Tobias Grosser9c7d1812017-02-09 23:24:54 +00003015 if (Array->getNumberOfDimensions() != 1)
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +00003016 continue;
Tobias Grosser9c7d1812017-02-09 23:24:54 +00003017 unsigned DivisibleSize = Array->getElemSizeInBytes();
3018 const SCEV *Subscript = Access->getSubscript(0);
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +00003019 while (!isDivisible(Subscript, DivisibleSize, *SE))
3020 DivisibleSize /= 2;
3021 auto *Ty = IntegerType::get(SE->getContext(), DivisibleSize * 8);
Tobias Grosser9c7d1812017-02-09 23:24:54 +00003022 Array->updateElementType(Ty);
Johannes Doerfert4d9bb8d2016-02-18 16:50:12 +00003023 }
3024
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003025 for (auto &Stmt : *this)
3026 for (auto &Access : Stmt)
3027 Access->updateDimensionality();
3028}
3029
Tobias Grosser491b7992016-12-02 05:21:22 +00003030void Scop::foldAccessRelations() {
3031 for (auto &Stmt : *this)
3032 for (auto &Access : Stmt)
3033 Access->foldAccessRelation();
3034}
3035
3036void Scop::assumeNoOutOfBounds() {
3037 for (auto &Stmt : *this)
3038 for (auto &Access : Stmt)
3039 Access->assumeNoOutOfBound();
3040}
3041
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003042void Scop::removeFromStmtMap(ScopStmt &Stmt) {
Tobias Grosserbd15d132017-08-31 03:15:56 +00003043 for (Instruction *Inst : Stmt.getInstructions())
3044 InstStmtMap.erase(Inst);
3045
3046 if (Stmt.isRegionStmt()) {
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003047 for (BasicBlock *BB : Stmt.getRegion()->blocks()) {
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003048 StmtMap.erase(BB);
Tobias Grosserbd15d132017-08-31 03:15:56 +00003049 // Skip entry basic block, as its instructions are already deleted as
3050 // part of the statement's instruction list.
3051 if (BB == Stmt.getEntryBlock())
3052 continue;
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003053 for (Instruction &Inst : *BB)
3054 InstStmtMap.erase(&Inst);
3055 }
Tobias Grosserbd15d132017-08-31 03:15:56 +00003056 } else {
Michael Kruse0c6c5552017-09-01 11:36:52 +00003057 auto StmtMapIt = StmtMap.find(Stmt.getBasicBlock());
3058 if (StmtMapIt != StmtMap.end())
3059 StmtMapIt->second.erase(std::remove(StmtMapIt->second.begin(),
3060 StmtMapIt->second.end(), &Stmt),
3061 StmtMapIt->second.end());
3062 for (Instruction *Inst : Stmt.getInstructions())
3063 InstStmtMap.erase(Inst);
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003064 }
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003065}
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003066
Michael Kruse192e7f72018-04-09 23:13:05 +00003067void Scop::removeStmts(std::function<bool(ScopStmt &)> ShouldDelete,
3068 bool AfterHoisting) {
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003069 for (auto StmtIt = Stmts.begin(), StmtEnd = Stmts.end(); StmtIt != StmtEnd;) {
3070 if (!ShouldDelete(*StmtIt)) {
3071 StmtIt++;
3072 continue;
3073 }
3074
Michael Kruse192e7f72018-04-09 23:13:05 +00003075 // Start with removing all of the statement's accesses including erasing it
3076 // from all maps that are pointing to them.
Michael Krusedb6f71e2018-04-10 01:20:41 +00003077 // Make a temporary copy because removing MAs invalidates the iterator.
3078 SmallVector<MemoryAccess *, 16> MAList(StmtIt->begin(), StmtIt->end());
3079 for (MemoryAccess *MA : MAList)
Michael Kruse192e7f72018-04-09 23:13:05 +00003080 StmtIt->removeSingleMemoryAccess(MA, AfterHoisting);
3081
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003082 removeFromStmtMap(*StmtIt);
3083 StmtIt = Stmts.erase(StmtIt);
3084 }
3085}
3086
3087void Scop::removeStmtNotInDomainMap() {
3088 auto ShouldDelete = [this](ScopStmt &Stmt) -> bool {
Michael Kruse842bdd02018-08-01 22:28:32 +00003089 isl::set Domain = DomainMap.lookup(Stmt.getEntryBlock());
3090 if (!Domain)
3091 return true;
3092 return Domain.is_empty();
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003093 };
Michael Kruse192e7f72018-04-09 23:13:05 +00003094 removeStmts(ShouldDelete, false);
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003095}
3096
3097void Scop::simplifySCoP(bool AfterHoisting) {
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003098 auto ShouldDelete = [AfterHoisting](ScopStmt &Stmt) -> bool {
Michael Kruse5369ea52018-04-20 18:55:44 +00003099 // Never delete statements that contain calls to debug functions.
3100 if (hasDebugCall(&Stmt))
3101 return false;
3102
Johannes Doerfert26404542016-05-10 12:19:47 +00003103 bool RemoveStmt = Stmt.isEmpty();
Johannes Doerfertf17a78e2015-10-04 15:00:05 +00003104
Tobias Grosser3012a0b2017-07-16 22:44:17 +00003105 // Remove read only statements only after invariant load hoisting.
Johannes Doerfert26404542016-05-10 12:19:47 +00003106 if (!RemoveStmt && AfterHoisting) {
Johannes Doerferteca9e892015-11-03 16:54:49 +00003107 bool OnlyRead = true;
3108 for (MemoryAccess *MA : Stmt) {
3109 if (MA->isRead())
3110 continue;
3111
3112 OnlyRead = false;
3113 break;
3114 }
3115
3116 RemoveStmt = OnlyRead;
3117 }
Tobias Grosser21cbcf02017-07-16 23:55:38 +00003118 return RemoveStmt;
3119 };
Johannes Doerferteca9e892015-11-03 16:54:49 +00003120
Michael Kruse192e7f72018-04-09 23:13:05 +00003121 removeStmts(ShouldDelete, AfterHoisting);
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003122}
3123
Johannes Doerfert8ab28032016-04-27 12:49:11 +00003124InvariantEquivClassTy *Scop::lookupInvariantEquivClass(Value *Val) {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003125 LoadInst *LInst = dyn_cast<LoadInst>(Val);
3126 if (!LInst)
3127 return nullptr;
3128
3129 if (Value *Rep = InvEquivClassVMap.lookup(LInst))
3130 LInst = cast<LoadInst>(Rep);
3131
Johannes Doerfert96e54712016-02-07 17:30:13 +00003132 Type *Ty = LInst->getType();
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003133 const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
Johannes Doerfert549768c2016-03-24 13:22:16 +00003134 for (auto &IAClass : InvariantEquivClasses) {
Tobias Grosserfaef9a72016-07-11 12:27:04 +00003135 if (PointerSCEV != IAClass.IdentifyingPointer || Ty != IAClass.AccessType)
Johannes Doerfert549768c2016-03-24 13:22:16 +00003136 continue;
3137
Tobias Grosser4e2d9c42016-07-11 12:15:10 +00003138 auto &MAs = IAClass.InvariantAccesses;
Johannes Doerfert549768c2016-03-24 13:22:16 +00003139 for (auto *MA : MAs)
3140 if (MA->getAccessInstruction() == Val)
3141 return &IAClass;
3142 }
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003143
3144 return nullptr;
3145}
3146
Michael Kruseb738ffa2017-06-28 13:02:43 +00003147ScopArrayInfo *Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *ElementType,
3148 ArrayRef<const SCEV *> Sizes,
3149 MemoryKind Kind,
3150 const char *BaseName) {
Roman Gareevd7754a12016-07-30 09:25:51 +00003151 assert((BasePtr || BaseName) &&
3152 "BasePtr and BaseName can not be nullptr at the same time.");
3153 assert(!(BasePtr && BaseName) && "BaseName is redundant.");
3154 auto &SAI = BasePtr ? ScopArrayInfoMap[std::make_pair(BasePtr, Kind)]
3155 : ScopArrayNameMap[BaseName];
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003156 if (!SAI) {
Johannes Doerfert3f52e352016-05-23 12:38:05 +00003157 auto &DL = getFunction().getParent()->getDataLayout();
Tobias Grossercc779502016-02-02 13:22:54 +00003158 SAI.reset(new ScopArrayInfo(BasePtr, ElementType, getIslCtx(), Sizes, Kind,
Roman Gareevd7754a12016-07-30 09:25:51 +00003159 DL, this, BaseName));
3160 ScopArrayInfoSet.insert(SAI.get());
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003161 } else {
Johannes Doerfert3ff22212016-02-14 22:31:39 +00003162 SAI->updateElementType(ElementType);
Tobias Grosser8286b832015-11-02 11:29:32 +00003163 // In case of mismatching array sizes, we bail out by setting the run-time
3164 // context to false.
Johannes Doerfert3ff22212016-02-14 22:31:39 +00003165 if (!SAI->updateSizes(Sizes))
Tobias Grosser8d4f6262015-12-12 09:52:26 +00003166 invalidate(DELINEARIZATION, DebugLoc());
Tobias Grosser99c70dd2015-09-26 08:55:54 +00003167 }
Tobias Grosserab671442015-05-23 05:58:27 +00003168 return SAI.get();
Johannes Doerfert1a28a892014-10-05 11:32:18 +00003169}
3170
Michael Kruseb738ffa2017-06-28 13:02:43 +00003171ScopArrayInfo *Scop::createScopArrayInfo(Type *ElementType,
3172 const std::string &BaseName,
3173 const std::vector<unsigned> &Sizes) {
Roman Gareevd7754a12016-07-30 09:25:51 +00003174 auto *DimSizeType = Type::getInt64Ty(getSE()->getContext());
3175 std::vector<const SCEV *> SCEVSizes;
3176
3177 for (auto size : Sizes)
Roman Gareevf5aff702016-09-12 17:08:31 +00003178 if (size)
3179 SCEVSizes.push_back(getSE()->getConstant(DimSizeType, size, false));
3180 else
3181 SCEVSizes.push_back(nullptr);
Roman Gareevd7754a12016-07-30 09:25:51 +00003182
Tobias Grosser4d5a9172017-01-14 20:25:44 +00003183 auto *SAI = getOrCreateScopArrayInfo(nullptr, ElementType, SCEVSizes,
3184 MemoryKind::Array, BaseName.c_str());
Roman Gareevd7754a12016-07-30 09:25:51 +00003185 return SAI;
3186}
3187
Tobias Grosserf3adab42017-05-10 10:59:58 +00003188const ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr,
3189 MemoryKind Kind) {
Tobias Grosser6abc75a2015-11-10 17:31:31 +00003190 auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
Tobias Grosserf3adab42017-05-10 10:59:58 +00003191 return SAI;
3192}
3193
3194const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
3195 auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind);
Johannes Doerfert1a28a892014-10-05 11:32:18 +00003196 assert(SAI && "No ScopArrayInfo available for this base pointer");
3197 return SAI;
3198}
3199
Tobias Grosser8ea1fc12017-08-06 19:52:38 +00003200std::string Scop::getContextStr() const { return getContext().to_str(); }
Johannes Doerfertb92e2182016-02-21 16:37:58 +00003201
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003202std::string Scop::getAssumedContextStr() const {
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003203 assert(AssumedContext && "Assumed context not yet built");
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003204 return AssumedContext.to_str();
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003205}
Johannes Doerfertb92e2182016-02-21 16:37:58 +00003206
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003207std::string Scop::getInvalidContextStr() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003208 return InvalidContext.to_str();
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003209}
Tobias Grosser75805372011-04-29 06:27:02 +00003210
3211std::string Scop::getNameStr() const {
3212 std::string ExitName, EntryName;
Siddharth Bhat07bee292017-06-02 08:01:22 +00003213 std::tie(EntryName, ExitName) = getEntryExitStr();
3214 return EntryName + "---" + ExitName;
3215}
3216
3217std::pair<std::string, std::string> Scop::getEntryExitStr() const {
3218 std::string ExitName, EntryName;
Tobias Grosser75805372011-04-29 06:27:02 +00003219 raw_string_ostream ExitStr(ExitName);
3220 raw_string_ostream EntryStr(EntryName);
3221
Tobias Grosserf240b482014-01-09 10:42:15 +00003222 R.getEntry()->printAsOperand(EntryStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00003223 EntryStr.str();
3224
3225 if (R.getExit()) {
Tobias Grosserf240b482014-01-09 10:42:15 +00003226 R.getExit()->printAsOperand(ExitStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00003227 ExitStr.str();
3228 } else
3229 ExitName = "FunctionExit";
3230
Siddharth Bhat07bee292017-06-02 08:01:22 +00003231 return std::make_pair(EntryName, ExitName);
Tobias Grosser75805372011-04-29 06:27:02 +00003232}
3233
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003234isl::set Scop::getContext() const { return Context; }
Tobias Grosserb65ccc42017-08-06 20:11:59 +00003235isl::space Scop::getParamSpace() const { return getContext().get_space(); }
Tobias Grosser37487052011-10-06 00:03:42 +00003236
Tobias Grosserb5563c62017-08-03 13:51:15 +00003237isl::space Scop::getFullParamSpace() const {
3238 std::vector<isl::id> FortranIDs;
3239 FortranIDs = getFortranArrayIds(arrays());
3240
3241 isl::space Space = isl::space::params_alloc(
3242 getIslCtx(), ParameterIds.size() + FortranIDs.size());
3243
3244 unsigned PDim = 0;
3245 for (const SCEV *Parameter : Parameters) {
Tobias Grosser9a635702017-08-06 19:31:27 +00003246 isl::id Id = getIdForParam(Parameter);
Tobias Grosserb5563c62017-08-03 13:51:15 +00003247 Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
3248 }
3249
3250 for (isl::id Id : FortranIDs)
3251 Space = Space.set_dim_id(isl::dim::param, PDim++, Id);
3252
3253 return Space;
3254}
3255
Tobias Grossere1270332017-08-06 21:42:09 +00003256isl::set Scop::getAssumedContext() const {
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003257 assert(AssumedContext && "Assumed context not yet built");
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003258 return AssumedContext;
Tobias Grossere86109f2013-10-29 21:05:49 +00003259}
3260
Michael Krusef3091bf2017-03-17 13:09:52 +00003261bool Scop::isProfitable(bool ScalarsAreUnprofitable) const {
Johannes Doerfert27d12d32016-05-10 16:38:09 +00003262 if (PollyProcessUnprofitable)
3263 return true;
3264
Johannes Doerfert27d12d32016-05-10 16:38:09 +00003265 if (isEmpty())
3266 return false;
3267
3268 unsigned OptimizableStmtsOrLoops = 0;
3269 for (auto &Stmt : *this) {
3270 if (Stmt.getNumIterators() == 0)
3271 continue;
3272
3273 bool ContainsArrayAccs = false;
3274 bool ContainsScalarAccs = false;
3275 for (auto *MA : Stmt) {
3276 if (MA->isRead())
3277 continue;
Michael Krusef3091bf2017-03-17 13:09:52 +00003278 ContainsArrayAccs |= MA->isLatestArrayKind();
3279 ContainsScalarAccs |= MA->isLatestScalarKind();
Johannes Doerfert27d12d32016-05-10 16:38:09 +00003280 }
3281
Michael Krusef3091bf2017-03-17 13:09:52 +00003282 if (!ScalarsAreUnprofitable || (ContainsArrayAccs && !ContainsScalarAccs))
Johannes Doerfert27d12d32016-05-10 16:38:09 +00003283 OptimizableStmtsOrLoops += Stmt.getNumIterators();
3284 }
3285
3286 return OptimizableStmtsOrLoops > 1;
3287}
3288
Johannes Doerfert5d5b3062015-08-20 18:06:30 +00003289bool Scop::hasFeasibleRuntimeContext() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003290 auto PositiveContext = getAssumedContext();
3291 auto NegativeContext = getInvalidContext();
3292 PositiveContext = addNonEmptyDomainConstraints(PositiveContext);
3293 // addNonEmptyDomainConstraints returns null if ScopStmts have a null domain
3294 if (!PositiveContext)
Johannes Doerfert94341c92016-04-23 13:00:27 +00003295 return false;
Johannes Doerfert94341c92016-04-23 13:00:27 +00003296
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003297 bool IsFeasible = !(PositiveContext.is_empty() ||
3298 PositiveContext.is_subset(NegativeContext));
3299 if (!IsFeasible)
3300 return false;
3301
3302 auto DomainContext = getDomains().params();
3303 IsFeasible = !DomainContext.is_subset(NegativeContext);
Dominik Adamski588fc9e2019-07-16 21:10:45 +00003304 IsFeasible &= !getContext().is_subset(NegativeContext);
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003305
Johannes Doerfert43788c52015-08-20 05:58:56 +00003306 return IsFeasible;
3307}
3308
Dominik Adamski588fc9e2019-07-16 21:10:45 +00003309isl::set Scop::addNonEmptyDomainConstraints(isl::set C) const {
3310 isl::set DomainContext = getDomains().params();
3311 return C.intersect_params(DomainContext);
3312}
3313
3314MemoryAccess *Scop::lookupBasePtrAccess(MemoryAccess *MA) {
3315 Value *PointerBase = MA->getOriginalBaseAddr();
3316
3317 auto *PointerBaseInst = dyn_cast<Instruction>(PointerBase);
3318 if (!PointerBaseInst)
3319 return nullptr;
3320
3321 auto *BasePtrStmt = getStmtFor(PointerBaseInst);
3322 if (!BasePtrStmt)
3323 return nullptr;
3324
3325 return BasePtrStmt->getArrayAccessOrNULLFor(PointerBaseInst);
3326}
3327
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003328static std::string toString(AssumptionKind Kind) {
3329 switch (Kind) {
3330 case ALIASING:
3331 return "No-aliasing";
3332 case INBOUNDS:
3333 return "Inbounds";
3334 case WRAPPING:
3335 return "No-overflows";
Johannes Doerfertc3596282016-04-25 14:01:36 +00003336 case UNSIGNED:
3337 return "Signed-unsigned";
Johannes Doerfert6462d8c2016-03-26 16:17:00 +00003338 case COMPLEXITY:
3339 return "Low complexity";
Johannes Doerfert27d12d32016-05-10 16:38:09 +00003340 case PROFITABLE:
3341 return "Profitable";
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003342 case ERRORBLOCK:
3343 return "No-error";
3344 case INFINITELOOP:
3345 return "Finite loop";
3346 case INVARIANTLOAD:
3347 return "Invariant load";
3348 case DELINEARIZATION:
3349 return "Delinearization";
3350 }
3351 llvm_unreachable("Unknown AssumptionKind!");
3352}
3353
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003354bool Scop::isEffectiveAssumption(isl::set Set, AssumptionSign Sign) {
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003355 if (Sign == AS_ASSUMPTION) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003356 if (Context.is_subset(Set))
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003357 return false;
3358
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003359 if (AssumedContext.is_subset(Set))
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003360 return false;
3361 } else {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003362 if (Set.is_disjoint(Context))
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003363 return false;
3364
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003365 if (Set.is_subset(InvalidContext))
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003366 return false;
3367 }
3368 return true;
3369}
3370
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003371bool Scop::trackAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3372 AssumptionSign Sign, BasicBlock *BB) {
Johannes Doerfert1a6b0f72016-06-06 12:16:10 +00003373 if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign))
3374 return false;
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003375
Johannes Doerfertb3265a32016-11-17 22:08:40 +00003376 // Do never emit trivial assumptions as they only clutter the output.
3377 if (!PollyRemarksMinimal) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003378 isl::set Univ;
Johannes Doerfertb3265a32016-11-17 22:08:40 +00003379 if (Sign == AS_ASSUMPTION)
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003380 Univ = isl::set::universe(Set.get_space());
Johannes Doerfertb3265a32016-11-17 22:08:40 +00003381
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003382 bool IsTrivial = (Sign == AS_RESTRICTION && Set.is_empty()) ||
3383 (Sign == AS_ASSUMPTION && Univ.is_equal(Set));
Johannes Doerfertb3265a32016-11-17 22:08:40 +00003384
3385 if (IsTrivial)
3386 return false;
3387 }
3388
Johannes Doerfertcd195322016-11-17 21:41:08 +00003389 switch (Kind) {
3390 case ALIASING:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003391 AssumptionsAliasing++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003392 break;
3393 case INBOUNDS:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003394 AssumptionsInbounds++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003395 break;
3396 case WRAPPING:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003397 AssumptionsWrapping++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003398 break;
3399 case UNSIGNED:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003400 AssumptionsUnsigned++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003401 break;
3402 case COMPLEXITY:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003403 AssumptionsComplexity++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003404 break;
3405 case PROFITABLE:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003406 AssumptionsUnprofitable++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003407 break;
3408 case ERRORBLOCK:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003409 AssumptionsErrorBlock++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003410 break;
3411 case INFINITELOOP:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003412 AssumptionsInfiniteLoop++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003413 break;
3414 case INVARIANTLOAD:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003415 AssumptionsInvariantLoad++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003416 break;
3417 case DELINEARIZATION:
Johannes Doerfert81aa6e82016-11-18 14:37:08 +00003418 AssumptionsDelinearization++;
Johannes Doerfertcd195322016-11-17 21:41:08 +00003419 break;
3420 }
3421
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003422 auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t";
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003423 std::string Msg = toString(Kind) + Suffix + Set.to_str();
Eli Friedmane737fc12017-07-17 23:58:33 +00003424 if (BB)
3425 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB)
3426 << Msg);
3427 else
3428 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc,
3429 R.getEntry())
3430 << Msg);
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003431 return true;
Johannes Doerfertd84493e2015-11-12 02:33:38 +00003432}
3433
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003434void Scop::addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3435 AssumptionSign Sign, BasicBlock *BB) {
Johannes Doerfert3bf6e4122016-04-12 13:27:35 +00003436 // Simplify the assumptions/restrictions first.
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003437 Set = Set.gist_params(getContext());
Johannes Doerfert3bf6e4122016-04-12 13:27:35 +00003438
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003439 if (!trackAssumption(Kind, Set, Loc, Sign, BB))
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003440 return;
Tobias Grosser20a4c0c2015-11-11 16:22:36 +00003441
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003442 if (Sign == AS_ASSUMPTION)
3443 AssumedContext = AssumedContext.intersect(Set).coalesce();
3444 else
3445 InvalidContext = InvalidContext.unite(Set).coalesce();
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003446}
3447
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003448void Scop::recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
3449 AssumptionSign Sign, BasicBlock *BB) {
3450 assert((Set.is_params() || BB) &&
Tobias Grosserf67433a2016-11-10 11:44:10 +00003451 "Assumptions without a basic block must be parameter sets");
Johannes Doerfert615e0b82016-04-12 13:28:39 +00003452 RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB});
Johannes Doerfert3bf6e4122016-04-12 13:27:35 +00003453}
3454
Eli Friedmane737fc12017-07-17 23:58:33 +00003455void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) {
Nicola Zaghen349506a2018-05-15 13:37:17 +00003456 LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n");
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003457 addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB);
Tobias Grosser8d4f6262015-12-12 09:52:26 +00003458}
3459
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003460isl::set Scop::getInvalidContext() const { return InvalidContext; }
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003461
Tobias Grosser75805372011-04-29 06:27:02 +00003462void Scop::printContext(raw_ostream &OS) const {
3463 OS << "Context:\n";
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003464 OS.indent(4) << Context << "\n";
Tobias Grosser60b54f12011-11-08 15:41:28 +00003465
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003466 OS.indent(4) << "Assumed Context:\n";
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003467 OS.indent(4) << AssumedContext << "\n";
Tobias Grosser5e6813d2014-07-02 17:47:48 +00003468
Johannes Doerfert066dbf32016-03-01 13:06:28 +00003469 OS.indent(4) << "Invalid Context:\n";
3470 OS.indent(4) << InvalidContext << "\n";
Johannes Doerfert883f8c12015-09-15 22:52:53 +00003471
Johannes Doerfert4e3bb7b2016-04-25 16:15:13 +00003472 unsigned Dim = 0;
3473 for (const SCEV *Parameter : Parameters)
3474 OS.indent(4) << "p" << Dim++ << ": " << *Parameter << "\n";
Tobias Grosser75805372011-04-29 06:27:02 +00003475}
3476
Johannes Doerfertb164c792014-09-18 11:17:17 +00003477void Scop::printAliasAssumptions(raw_ostream &OS) const {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003478 int noOfGroups = 0;
3479 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) {
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003480 if (Pair.second.size() == 0)
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003481 noOfGroups += 1;
3482 else
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003483 noOfGroups += Pair.second.size();
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003484 }
3485
Tobias Grosserbb853c22015-07-25 12:31:03 +00003486 OS.indent(4) << "Alias Groups (" << noOfGroups << "):\n";
Johannes Doerfertb164c792014-09-18 11:17:17 +00003487 if (MinMaxAliasGroups.empty()) {
3488 OS.indent(8) << "n/a\n";
3489 return;
3490 }
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003491
Tobias Grosserbb853c22015-07-25 12:31:03 +00003492 for (const MinMaxVectorPairTy &Pair : MinMaxAliasGroups) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003493
3494 // If the group has no read only accesses print the write accesses.
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003495 if (Pair.second.empty()) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003496 OS.indent(8) << "[[";
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003497 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003498 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3499 << ">";
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003500 }
3501 OS << " ]]\n";
3502 }
3503
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003504 for (const MinMaxAccessTy &MMAReadOnly : Pair.second) {
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003505 OS.indent(8) << "[[";
Tobias Grosserbb853c22015-07-25 12:31:03 +00003506 OS << " <" << MMAReadOnly.first << ", " << MMAReadOnly.second << ">";
Johannes Doerfert210b09a2015-07-26 13:14:38 +00003507 for (const MinMaxAccessTy &MMANonReadOnly : Pair.first) {
Tobias Grosserbb853c22015-07-25 12:31:03 +00003508 OS << " <" << MMANonReadOnly.first << ", " << MMANonReadOnly.second
3509 << ">";
Johannes Doerfert338b42c2015-07-23 17:04:54 +00003510 }
3511 OS << " ]]\n";
3512 }
Johannes Doerfertb164c792014-09-18 11:17:17 +00003513 }
3514}
3515
Michael Krusecd4c9772017-07-21 15:35:53 +00003516void Scop::printStatements(raw_ostream &OS, bool PrintInstructions) const {
Tobias Grosser75805372011-04-29 06:27:02 +00003517 OS << "Statements {\n";
3518
Michael Krusecd4c9772017-07-21 15:35:53 +00003519 for (const ScopStmt &Stmt : *this) {
3520 OS.indent(4);
3521 Stmt.print(OS, PrintInstructions);
3522 }
Tobias Grosser75805372011-04-29 06:27:02 +00003523
3524 OS.indent(4) << "}\n";
3525}
3526
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003527void Scop::printArrayInfo(raw_ostream &OS) const {
3528 OS << "Arrays {\n";
3529
Tobias Grosserab671442015-05-23 05:58:27 +00003530 for (auto &Array : arrays())
Roman Gareevd7754a12016-07-30 09:25:51 +00003531 Array->print(OS);
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003532
3533 OS.indent(4) << "}\n";
Tobias Grosserd46fd5e2015-08-12 15:27:16 +00003534
3535 OS.indent(4) << "Arrays (Bounds as pw_affs) {\n";
3536
3537 for (auto &Array : arrays())
Roman Gareevd7754a12016-07-30 09:25:51 +00003538 Array->print(OS, /* SizeAsPwAff */ true);
Tobias Grosserd46fd5e2015-08-12 15:27:16 +00003539
3540 OS.indent(4) << "}\n";
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003541}
3542
Michael Krusecd4c9772017-07-21 15:35:53 +00003543void Scop::print(raw_ostream &OS, bool PrintInstructions) const {
Johannes Doerfert3f52e352016-05-23 12:38:05 +00003544 OS.indent(4) << "Function: " << getFunction().getName() << "\n";
Tobias Grosser483fdd42014-03-18 18:05:38 +00003545 OS.indent(4) << "Region: " << getNameStr() << "\n";
David Peixottodc0a11c2015-01-13 18:31:55 +00003546 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n";
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003547 OS.indent(4) << "Invariant Accesses: {\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003548 for (const auto &IAClass : InvariantEquivClasses) {
Tobias Grosser4e2d9c42016-07-11 12:15:10 +00003549 const auto &MAs = IAClass.InvariantAccesses;
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003550 if (MAs.empty()) {
Tobias Grosser4e2d9c42016-07-11 12:15:10 +00003551 OS.indent(12) << "Class Pointer: " << *IAClass.IdentifyingPointer << "\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003552 } else {
Johannes Doerfertaf3e3012015-10-18 12:39:19 +00003553 MAs.front()->print(OS);
Tobias Grosser4e2d9c42016-07-11 12:15:10 +00003554 OS.indent(12) << "Execution Context: " << IAClass.ExecutionContext
3555 << "\n";
Johannes Doerfert697fdf82015-10-09 17:12:26 +00003556 }
Johannes Doerfertc1db67e2015-09-29 23:47:21 +00003557 }
3558 OS.indent(4) << "}\n";
Tobias Grosser75805372011-04-29 06:27:02 +00003559 printContext(OS.indent(4));
Tobias Grosser49ad36c2015-05-20 08:05:31 +00003560 printArrayInfo(OS.indent(4));
Johannes Doerfertb164c792014-09-18 11:17:17 +00003561 printAliasAssumptions(OS);
Michael Krusecd4c9772017-07-21 15:35:53 +00003562 printStatements(OS.indent(4), PrintInstructions);
Tobias Grosser75805372011-04-29 06:27:02 +00003563}
3564
Michael Kruse5d518462017-07-21 15:54:07 +00003565#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Michael Krusee1860132017-07-21 15:54:13 +00003566LLVM_DUMP_METHOD void Scop::dump() const { print(dbgs(), true); }
Michael Kruse5d518462017-07-21 15:54:07 +00003567#endif
Tobias Grosser75805372011-04-29 06:27:02 +00003568
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003569isl::ctx Scop::getIslCtx() const { return IslCtx.get(); }
Tobias Grosser75805372011-04-29 06:27:02 +00003570
Johannes Doerfert3e48ee22016-04-29 10:44:41 +00003571__isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
3572 bool NonNegative) {
Johannes Doerfert6462d8c2016-03-26 16:17:00 +00003573 // First try to use the SCEVAffinator to generate a piecewise defined
3574 // affine function from @p E in the context of @p BB. If that tasks becomes to
3575 // complex the affinator might return a nullptr. In such a case we invalidate
3576 // the SCoP and return a dummy value. This way we do not need to add error
Tobias Grossercdbe5c92017-01-06 17:30:34 +00003577 // handling code to all users of this function.
Johannes Doerfertac9c32e2016-04-23 14:31:17 +00003578 auto PWAC = Affinator.getPwAff(E, BB);
Johannes Doerfert3e48ee22016-04-29 10:44:41 +00003579 if (PWAC.first) {
Johannes Doerfert56b37762016-05-10 11:45:46 +00003580 // TODO: We could use a heuristic and either use:
3581 // SCEVAffinator::takeNonNegativeAssumption
3582 // or
3583 // SCEVAffinator::interpretAsUnsigned
3584 // to deal with unsigned or "NonNegative" SCEVs.
Johannes Doerfert3e48ee22016-04-29 10:44:41 +00003585 if (NonNegative)
3586 Affinator.takeNonNegativeAssumption(PWAC);
Johannes Doerfertac9c32e2016-04-23 14:31:17 +00003587 return PWAC;
Johannes Doerfert3e48ee22016-04-29 10:44:41 +00003588 }
Johannes Doerfert6462d8c2016-03-26 16:17:00 +00003589
3590 auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
Eli Friedmane737fc12017-07-17 23:58:33 +00003591 invalidate(COMPLEXITY, DL, BB);
Johannes Doerfert6462d8c2016-03-26 16:17:00 +00003592 return Affinator.getPwAff(SE->getZero(E->getType()), BB);
Johannes Doerfert574182d2015-08-12 10:19:50 +00003593}
3594
Tobias Grosser31df6f32017-08-06 21:42:25 +00003595isl::union_set Scop::getDomains() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003596 isl_space *EmptySpace = isl_space_params_alloc(getIslCtx().get(), 0);
Tobias Grosser941cb7d2017-03-17 09:02:50 +00003597 isl_union_set *Domain = isl_union_set_empty(EmptySpace);
Tobias Grosser5f9a7622012-02-14 14:02:40 +00003598
Tobias Grosser808cd692015-07-14 09:33:13 +00003599 for (const ScopStmt &Stmt : *this)
Tobias Grosserdcf8d692017-08-06 16:39:52 +00003600 Domain = isl_union_set_add_set(Domain, Stmt.getDomain().release());
Tobias Grosser5f9a7622012-02-14 14:02:40 +00003601
Tobias Grosser31df6f32017-08-06 21:42:25 +00003602 return isl::manage(Domain);
Tobias Grosser5f9a7622012-02-14 14:02:40 +00003603}
3604
Tobias Grosser61bd3a42017-08-06 21:42:38 +00003605isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) {
Johannes Doerfertac9c32e2016-04-23 14:31:17 +00003606 PWACtx PWAC = getPwAff(E, BB);
Philip Pfaffed98dbee2017-12-06 21:02:22 +00003607 return PWAC.first;
Johannes Doerfertac9c32e2016-04-23 14:31:17 +00003608}
3609
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003610isl::union_map
Tobias Grossere5a35142015-11-12 14:07:09 +00003611Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) {
Tobias Grosserb65ccc42017-08-06 20:11:59 +00003612 isl::union_map Accesses = isl::union_map::empty(getParamSpace());
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003613
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003614 for (ScopStmt &Stmt : *this) {
3615 for (MemoryAccess *MA : Stmt) {
Tobias Grossere5a35142015-11-12 14:07:09 +00003616 if (!Predicate(*MA))
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003617 continue;
3618
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003619 isl::set Domain = Stmt.getDomain();
3620 isl::map AccessDomain = MA->getAccessRelation();
3621 AccessDomain = AccessDomain.intersect_domain(Domain);
3622 Accesses = Accesses.add_map(AccessDomain);
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003623 }
3624 }
Tobias Grosser206e9e32017-07-24 16:22:27 +00003625
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003626 return Accesses.coalesce();
Tobias Grossere5a35142015-11-12 14:07:09 +00003627}
3628
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003629isl::union_map Scop::getMustWrites() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003630 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMustWrite(); });
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003631}
3632
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003633isl::union_map Scop::getMayWrites() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003634 return getAccessesOfType([](MemoryAccess &MA) { return MA.isMayWrite(); });
Tobias Grosser780ce0f2014-07-11 07:12:10 +00003635}
3636
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003637isl::union_map Scop::getWrites() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003638 return getAccessesOfType([](MemoryAccess &MA) { return MA.isWrite(); });
Tobias Grosser37eb4222014-02-20 21:43:54 +00003639}
3640
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003641isl::union_map Scop::getReads() {
Tobias Grossere5a35142015-11-12 14:07:09 +00003642 return getAccessesOfType([](MemoryAccess &MA) { return MA.isRead(); });
Tobias Grosser37eb4222014-02-20 21:43:54 +00003643}
3644
Tobias Grosser5ab39ff2017-08-06 19:22:27 +00003645isl::union_map Scop::getAccesses() {
Tobias Grosser2ac23382015-11-12 14:07:13 +00003646 return getAccessesOfType([](MemoryAccess &MA) { return true; });
3647}
3648
Tobias Grosserfa03cb72017-08-17 22:04:53 +00003649isl::union_map Scop::getAccesses(ScopArrayInfo *Array) {
3650 return getAccessesOfType(
3651 [Array](MemoryAccess &MA) { return MA.getScopArrayInfo() == Array; });
3652}
3653
Tobias Grosser61bd3a42017-08-06 21:42:38 +00003654isl::union_map Scop::getSchedule() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003655 auto Tree = getScheduleTree();
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003656 return Tree.get_map();
Tobias Grosser808cd692015-07-14 09:33:13 +00003657}
Tobias Grosser37eb4222014-02-20 21:43:54 +00003658
Tobias Grosser61bd3a42017-08-06 21:42:38 +00003659isl::schedule Scop::getScheduleTree() const {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003660 return Schedule.intersect_domain(getDomains());
Tobias Grosser808cd692015-07-14 09:33:13 +00003661}
Tobias Grosserbc4ef902014-06-28 08:59:38 +00003662
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003663void Scop::setSchedule(isl::union_map NewSchedule) {
3664 auto S = isl::schedule::from_domain(getDomains());
3665 Schedule = S.insert_partial_schedule(
3666 isl::multi_union_pw_aff::from_union_map(NewSchedule));
Michael Kruse2dab88e2018-06-06 21:37:35 +00003667 ScheduleModified = true;
Tobias Grosser808cd692015-07-14 09:33:13 +00003668}
3669
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003670void Scop::setScheduleTree(isl::schedule NewSchedule) {
Tobias Grosser808cd692015-07-14 09:33:13 +00003671 Schedule = NewSchedule;
Michael Kruse2dab88e2018-06-06 21:37:35 +00003672 ScheduleModified = true;
Tobias Grosser37eb4222014-02-20 21:43:54 +00003673}
3674
Tobias Grosser990cbb42017-08-14 06:49:01 +00003675bool Scop::restrictDomains(isl::union_set Domain) {
Tobias Grosser37eb4222014-02-20 21:43:54 +00003676 bool Changed = false;
Tobias Grosser7c3bad52015-05-27 05:16:57 +00003677 for (ScopStmt &Stmt : *this) {
Tobias Grosser990cbb42017-08-14 06:49:01 +00003678 isl::union_set StmtDomain = isl::union_set(Stmt.getDomain());
3679 isl::union_set NewStmtDomain = StmtDomain.intersect(Domain);
Tobias Grosser37eb4222014-02-20 21:43:54 +00003680
Tobias Grosser990cbb42017-08-14 06:49:01 +00003681 if (StmtDomain.is_subset(NewStmtDomain))
Tobias Grosser37eb4222014-02-20 21:43:54 +00003682 continue;
Tobias Grosser37eb4222014-02-20 21:43:54 +00003683
3684 Changed = true;
3685
Tobias Grosser990cbb42017-08-14 06:49:01 +00003686 NewStmtDomain = NewStmtDomain.coalesce();
Tobias Grosser37eb4222014-02-20 21:43:54 +00003687
Tobias Grosser990cbb42017-08-14 06:49:01 +00003688 if (NewStmtDomain.is_empty())
Tobias Grosserdcf8d692017-08-06 16:39:52 +00003689 Stmt.restrictDomain(isl::set::empty(Stmt.getDomainSpace()));
Tobias Grosser990cbb42017-08-14 06:49:01 +00003690 else
3691 Stmt.restrictDomain(isl::set(NewStmtDomain));
Tobias Grosser37eb4222014-02-20 21:43:54 +00003692 }
Tobias Grosser37eb4222014-02-20 21:43:54 +00003693 return Changed;
3694}
3695
Tobias Grosser75805372011-04-29 06:27:02 +00003696ScalarEvolution *Scop::getSE() const { return SE; }
3697
Tobias Grosserc80d6972016-09-02 06:33:33 +00003698// Create an isl_multi_union_aff that defines an identity mapping from the
3699// elements of USet to their N-th dimension.
Tobias Grosser808cd692015-07-14 09:33:13 +00003700//
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003701// # Example:
3702//
3703// Domain: { A[i,j]; B[i,j,k] }
3704// N: 1
3705//
3706// Resulting Mapping: { {A[i,j] -> [(j)]; B[i,j,k] -> [(j)] }
3707//
3708// @param USet A union set describing the elements for which to generate a
3709// mapping.
Tobias Grosser808cd692015-07-14 09:33:13 +00003710// @param N The dimension to map to.
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003711// @returns A mapping from USet to its N-th dimension.
Tobias Grosser99320862017-05-26 17:22:03 +00003712static isl::multi_union_pw_aff mapToDimension(isl::union_set USet, int N) {
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003713 assert(N >= 0);
Tobias Grosserc900633d2015-12-21 23:01:53 +00003714 assert(USet);
Siddharth Bhat8bb436e2017-05-29 11:34:29 +00003715 assert(!USet.is_empty());
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00003716
Tobias Grosser99320862017-05-26 17:22:03 +00003717 auto Result = isl::union_pw_multi_aff::empty(USet.get_space());
Tobias Grosser808cd692015-07-14 09:33:13 +00003718
Tobias Grosser31e29a42018-07-16 19:04:16 +00003719 for (isl::set S : USet.get_set_list()) {
Tobias Grosser99320862017-05-26 17:22:03 +00003720 int Dim = S.dim(isl::dim::set);
3721 auto PMA = isl::pw_multi_aff::project_out_map(S.get_space(), isl::dim::set,
3722 N, Dim - N);
3723 if (N > 1)
3724 PMA = PMA.drop_dims(isl::dim::out, 0, N - 1);
Tobias Grosser808cd692015-07-14 09:33:13 +00003725
Tobias Grosser99320862017-05-26 17:22:03 +00003726 Result = Result.add_pw_multi_aff(PMA);
Tobias Grosser31e29a42018-07-16 19:04:16 +00003727 }
Tobias Grossercbf7ae82015-12-21 22:45:53 +00003728
Tobias Grosser99320862017-05-26 17:22:03 +00003729 return isl::multi_union_pw_aff(isl::union_pw_multi_aff(Result));
Tobias Grosser808cd692015-07-14 09:33:13 +00003730}
3731
Michael Krused6e22082018-01-18 15:15:38 +00003732void Scop::addScopStmt(BasicBlock *BB, StringRef Name, Loop *SurroundingLoop,
3733 std::vector<Instruction *> Instructions) {
Hongbin Zhenga8fb73f2016-11-21 20:09:40 +00003734 assert(BB && "Unexpected nullptr!");
Michael Krused6e22082018-01-18 15:15:38 +00003735 Stmts.emplace_back(*this, *BB, Name, SurroundingLoop, Instructions);
Hongbin Zhenga8fb73f2016-11-21 20:09:40 +00003736 auto *Stmt = &Stmts.back();
Michael Kruse4dfa7322017-07-18 15:41:49 +00003737 StmtMap[BB].push_back(Stmt);
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003738 for (Instruction *Inst : Instructions) {
3739 assert(!InstStmtMap.count(Inst) &&
3740 "Unexpected statement corresponding to the instruction.");
3741 InstStmtMap[Inst] = Stmt;
3742 }
Hongbin Zhenga8fb73f2016-11-21 20:09:40 +00003743}
3744
Michael Krused6e22082018-01-18 15:15:38 +00003745void Scop::addScopStmt(Region *R, StringRef Name, Loop *SurroundingLoop,
Tobias Grosserbd15d132017-08-31 03:15:56 +00003746 std::vector<Instruction *> Instructions) {
Hongbin Zhenga8fb73f2016-11-21 20:09:40 +00003747 assert(R && "Unexpected nullptr!");
Michael Krused6e22082018-01-18 15:15:38 +00003748 Stmts.emplace_back(*this, *R, Name, SurroundingLoop, Instructions);
Hongbin Zhenga8fb73f2016-11-21 20:09:40 +00003749 auto *Stmt = &Stmts.back();
Tobias Grosserbd15d132017-08-31 03:15:56 +00003750
3751 for (Instruction *Inst : Instructions) {
3752 assert(!InstStmtMap.count(Inst) &&
3753 "Unexpected statement corresponding to the instruction.");
3754 InstStmtMap[Inst] = Stmt;
3755 }
3756
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003757 for (BasicBlock *BB : R->blocks()) {
Michael Kruse4dfa7322017-07-18 15:41:49 +00003758 StmtMap[BB].push_back(Stmt);
Tobias Grosserbd15d132017-08-31 03:15:56 +00003759 if (BB == R->getEntry())
3760 continue;
Michael Krusecd3b9fe2017-08-09 16:45:37 +00003761 for (Instruction &Inst : *BB) {
3762 assert(!InstStmtMap.count(&Inst) &&
3763 "Unexpected statement corresponding to the instruction.");
3764 InstStmtMap[&Inst] = Stmt;
3765 }
3766 }
Tobias Grosser808cd692015-07-14 09:33:13 +00003767}
3768
Tobias Grosser85048ef2017-08-06 17:24:59 +00003769ScopStmt *Scop::addScopStmt(isl::map SourceRel, isl::map TargetRel,
3770 isl::set Domain) {
Tobias Grossereba86a12016-11-09 04:24:49 +00003771#ifndef NDEBUG
Tobias Grosser85048ef2017-08-06 17:24:59 +00003772 isl::set SourceDomain = SourceRel.domain();
3773 isl::set TargetDomain = TargetRel.domain();
3774 assert(Domain.is_subset(TargetDomain) &&
Tobias Grosser744740a2016-11-05 21:02:43 +00003775 "Target access not defined for complete statement domain");
Tobias Grosser85048ef2017-08-06 17:24:59 +00003776 assert(Domain.is_subset(SourceDomain) &&
Tobias Grosser744740a2016-11-05 21:02:43 +00003777 "Source access not defined for complete statement domain");
Tobias Grossereba86a12016-11-09 04:24:49 +00003778#endif
Roman Gareevb3224ad2016-09-14 06:26:09 +00003779 Stmts.emplace_back(*this, SourceRel, TargetRel, Domain);
3780 CopyStmtsNum++;
3781 return &(Stmts.back());
3782}
3783
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003784void Scop::buildSchedule(LoopInfo &LI) {
Johannes Doerfertef744432016-05-23 12:42:38 +00003785 Loop *L = getLoopSurroundingScop(*this, LI);
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003786 LoopStackTy LoopStack({LoopStackElementTy(L, nullptr, 0)});
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003787 buildSchedule(getRegion().getNode(), LoopStack, LI);
Tobias Grosser151ae322016-04-03 19:36:52 +00003788 assert(LoopStack.size() == 1 && LoopStack.back().L == L);
3789 Schedule = LoopStack[0].Schedule;
Johannes Doerfertf9711ef2016-01-06 12:59:23 +00003790}
3791
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003792/// To generate a schedule for the elements in a Region we traverse the Region
3793/// in reverse-post-order and add the contained RegionNodes in traversal order
3794/// to the schedule of the loop that is currently at the top of the LoopStack.
3795/// For loop-free codes, this results in a correct sequential ordering.
3796///
3797/// Example:
3798/// bb1(0)
3799/// / \.
3800/// bb2(1) bb3(2)
3801/// \ / \.
3802/// bb4(3) bb5(4)
3803/// \ /
3804/// bb6(5)
3805///
3806/// Including loops requires additional processing. Whenever a loop header is
3807/// encountered, the corresponding loop is added to the @p LoopStack. Starting
3808/// from an empty schedule, we first process all RegionNodes that are within
3809/// this loop and complete the sequential schedule at this loop-level before
3810/// processing about any other nodes. To implement this
3811/// loop-nodes-first-processing, the reverse post-order traversal is
3812/// insufficient. Hence, we additionally check if the traversal yields
3813/// sub-regions or blocks that are outside the last loop on the @p LoopStack.
3814/// These region-nodes are then queue and only traverse after the all nodes
3815/// within the current loop have been processed.
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003816void Scop::buildSchedule(Region *R, LoopStackTy &LoopStack, LoopInfo &LI) {
Johannes Doerfertef744432016-05-23 12:42:38 +00003817 Loop *OuterScopLoop = getLoopSurroundingScop(*this, LI);
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003818
3819 ReversePostOrderTraversal<Region *> RTraversal(R);
3820 std::deque<RegionNode *> WorkList(RTraversal.begin(), RTraversal.end());
3821 std::deque<RegionNode *> DelayList;
3822 bool LastRNWaiting = false;
3823
3824 // Iterate over the region @p R in reverse post-order but queue
3825 // sub-regions/blocks iff they are not part of the last encountered but not
3826 // completely traversed loop. The variable LastRNWaiting is a flag to indicate
3827 // that we queued the last sub-region/block from the reverse post-order
3828 // iterator. If it is set we have to explore the next sub-region/block from
3829 // the iterator (if any) to guarantee progress. If it is not set we first try
3830 // the next queued sub-region/blocks.
3831 while (!WorkList.empty() || !DelayList.empty()) {
3832 RegionNode *RN;
3833
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00003834 if ((LastRNWaiting && !WorkList.empty()) || DelayList.empty()) {
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003835 RN = WorkList.front();
3836 WorkList.pop_front();
3837 LastRNWaiting = false;
3838 } else {
3839 RN = DelayList.front();
3840 DelayList.pop_front();
3841 }
3842
3843 Loop *L = getRegionNodeLoop(RN, LI);
Johannes Doerfert952b5302016-05-23 12:40:48 +00003844 if (!contains(L))
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003845 L = OuterScopLoop;
3846
Tobias Grosser151ae322016-04-03 19:36:52 +00003847 Loop *LastLoop = LoopStack.back().L;
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003848 if (LastLoop != L) {
Johannes Doerfertd5edbd62016-04-03 23:09:06 +00003849 if (LastLoop && !LastLoop->contains(L)) {
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003850 LastRNWaiting = true;
3851 DelayList.push_back(RN);
3852 continue;
3853 }
3854 LoopStack.push_back({L, nullptr, 0});
3855 }
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003856 buildSchedule(RN, LoopStack, LI);
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003857 }
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003858}
3859
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003860void Scop::buildSchedule(RegionNode *RN, LoopStackTy &LoopStack, LoopInfo &LI) {
Tobias Grosser8362c262016-01-06 15:30:06 +00003861 if (RN->isSubRegion()) {
3862 auto *LocalRegion = RN->getNodeAs<Region>();
Johannes Doerfertffd222f2016-05-19 12:34:57 +00003863 if (!isNonAffineSubRegion(LocalRegion)) {
3864 buildSchedule(LocalRegion, LoopStack, LI);
Tobias Grosser8362c262016-01-06 15:30:06 +00003865 return;
3866 }
3867 }
Michael Kruse046dde42015-08-10 13:01:57 +00003868
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003869 assert(LoopStack.rbegin() != LoopStack.rend());
3870 auto LoopData = LoopStack.rbegin();
3871 LoopData->NumBlocksProcessed += getNumBlocksInRegionNode(RN);
Tobias Grosser8362c262016-01-06 15:30:06 +00003872
Michael Kruse1ce67912017-07-20 17:18:58 +00003873 for (auto *Stmt : getStmtListFor(RN)) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003874 isl::union_set UDomain{Stmt->getDomain()};
3875 auto StmtSchedule = isl::schedule::from_domain(UDomain);
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003876 LoopData->Schedule = combineInSequence(LoopData->Schedule, StmtSchedule);
Tobias Grosser8362c262016-01-06 15:30:06 +00003877 }
3878
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003879 // Check if we just processed the last node in this loop. If we did, finalize
3880 // the loop by:
3881 //
3882 // - adding new schedule dimensions
3883 // - folding the resulting schedule into the parent loop schedule
3884 // - dropping the loop schedule from the LoopStack.
3885 //
3886 // Then continue to check surrounding loops, which might also have been
3887 // completed by this node.
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003888 size_t Dimension = LoopStack.size();
3889 while (LoopData->L &&
3890 LoopData->NumBlocksProcessed == getNumBlocksInLoop(LoopData->L)) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003891 isl::schedule Schedule = LoopData->Schedule;
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003892 auto NumBlocksProcessed = LoopData->NumBlocksProcessed;
Tobias Grosser8362c262016-01-06 15:30:06 +00003893
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003894 assert(std::next(LoopData) != LoopStack.rend());
3895 ++LoopData;
3896 --Dimension;
Tobias Grosser8362c262016-01-06 15:30:06 +00003897
Tobias Grosserc2fd8b42016-02-01 11:54:13 +00003898 if (Schedule) {
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003899 isl::union_set Domain = Schedule.get_domain();
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003900 isl::multi_union_pw_aff MUPA = mapToDimension(Domain, Dimension);
Philip Pfaffe00fd43b2017-11-19 22:13:34 +00003901 Schedule = Schedule.insert_partial_schedule(MUPA);
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003902 LoopData->Schedule = combineInSequence(LoopData->Schedule, Schedule);
Tobias Grosser75805372011-04-29 06:27:02 +00003903 }
Johannes Doerfertb68cffb2015-09-10 15:27:46 +00003904
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003905 LoopData->NumBlocksProcessed += NumBlocksProcessed;
Tobias Grosser808cd692015-07-14 09:33:13 +00003906 }
Philip Pfaffe8dd0f472017-11-16 16:35:19 +00003907 // Now pop all loops processed up there from the LoopStack
3908 LoopStack.erase(LoopStack.begin() + Dimension, LoopStack.end());
Tobias Grosser75805372011-04-29 06:27:02 +00003909}
3910
Michael Kruse6eba4b12017-07-20 17:08:50 +00003911ArrayRef<ScopStmt *> Scop::getStmtListFor(BasicBlock *BB) const {
3912 auto StmtMapIt = StmtMap.find(BB);
3913 if (StmtMapIt == StmtMap.end())
3914 return {};
Michael Kruse6eba4b12017-07-20 17:08:50 +00003915 return StmtMapIt->second;
3916}
3917
Michael Krusea230f222018-01-23 23:56:36 +00003918ScopStmt *Scop::getIncomingStmtFor(const Use &U) const {
3919 auto *PHI = cast<PHINode>(U.getUser());
3920 BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
3921
3922 // If the value is a non-synthesizable from the incoming block, use the
3923 // statement that contains it as user statement.
3924 if (auto *IncomingInst = dyn_cast<Instruction>(U.get())) {
3925 if (IncomingInst->getParent() == IncomingBB) {
3926 if (ScopStmt *IncomingStmt = getStmtFor(IncomingInst))
3927 return IncomingStmt;
3928 }
3929 }
3930
3931 // Otherwise, use the epilogue/last statement.
3932 return getLastStmtFor(IncomingBB);
3933}
3934
Michael Kruse6eba4b12017-07-20 17:08:50 +00003935ScopStmt *Scop::getLastStmtFor(BasicBlock *BB) const {
3936 ArrayRef<ScopStmt *> StmtList = getStmtListFor(BB);
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00003937 if (!StmtList.empty())
Michael Kruse6eba4b12017-07-20 17:08:50 +00003938 return StmtList.back();
3939 return nullptr;
3940}
3941
Michael Kruse1ce67912017-07-20 17:18:58 +00003942ArrayRef<ScopStmt *> Scop::getStmtListFor(RegionNode *RN) const {
Michael Kruse6f7721f2016-02-24 22:08:19 +00003943 if (RN->isSubRegion())
Michael Kruse1ce67912017-07-20 17:18:58 +00003944 return getStmtListFor(RN->getNodeAs<Region>());
3945 return getStmtListFor(RN->getNodeAs<BasicBlock>());
Michael Kruse6f7721f2016-02-24 22:08:19 +00003946}
3947
Michael Kruse1ce67912017-07-20 17:18:58 +00003948ArrayRef<ScopStmt *> Scop::getStmtListFor(Region *R) const {
3949 return getStmtListFor(R->getEntry());
Michael Krusea902ba62015-12-13 19:21:45 +00003950}
3951
Johannes Doerfert96425c22015-08-30 21:13:53 +00003952int Scop::getRelativeLoopDepth(const Loop *L) const {
Philip Pfaffe1a0128f2017-05-24 18:39:39 +00003953 if (!L || !R.contains(L))
Johannes Doerfert96425c22015-08-30 21:13:53 +00003954 return -1;
Philip Pfaffe1a0128f2017-05-24 18:39:39 +00003955 // outermostLoopInRegion always returns nullptr for top level regions
3956 if (R.isTopLevelRegion()) {
3957 // LoopInfo's depths start at 1, we start at 0
3958 return L->getLoopDepth() - 1;
3959 } else {
3960 Loop *OuterLoop = R.outermostLoopInRegion(const_cast<Loop *>(L));
3961 assert(OuterLoop);
3962 return L->getLoopDepth() - OuterLoop->getLoopDepth();
3963 }
Johannes Doerfertd020b772015-08-27 06:53:52 +00003964}
3965
Roman Gareevd7754a12016-07-30 09:25:51 +00003966ScopArrayInfo *Scop::getArrayInfoByName(const std::string BaseName) {
3967 for (auto &SAI : arrays()) {
3968 if (SAI->getName() == BaseName)
3969 return SAI;
3970 }
3971 return nullptr;
3972}
3973
Michael Kruse8b805802017-07-19 17:11:25 +00003974void Scop::addAccessData(MemoryAccess *Access) {
3975 const ScopArrayInfo *SAI = Access->getOriginalScopArrayInfo();
3976 assert(SAI && "can only use after access relations have been constructed");
3977
3978 if (Access->isOriginalValueKind() && Access->isRead())
3979 ValueUseAccs[SAI].push_back(Access);
3980 else if (Access->isOriginalAnyPHIKind() && Access->isWrite())
3981 PHIIncomingAccs[SAI].push_back(Access);
3982}
3983
3984void Scop::removeAccessData(MemoryAccess *Access) {
Michael Kruse6d7a7892017-09-21 14:23:11 +00003985 if (Access->isOriginalValueKind() && Access->isWrite()) {
3986 ValueDefAccs.erase(Access->getAccessValue());
3987 } else if (Access->isOriginalValueKind() && Access->isRead()) {
Michael Kruse8b805802017-07-19 17:11:25 +00003988 auto &Uses = ValueUseAccs[Access->getScopArrayInfo()];
Michael Kruse7de61662018-04-09 23:13:01 +00003989 auto NewEnd = std::remove(Uses.begin(), Uses.end(), Access);
3990 Uses.erase(NewEnd, Uses.end());
Michael Kruse6d7a7892017-09-21 14:23:11 +00003991 } else if (Access->isOriginalPHIKind() && Access->isRead()) {
3992 PHINode *PHI = cast<PHINode>(Access->getAccessInstruction());
3993 PHIReadAccs.erase(PHI);
Michael Kruse8b805802017-07-19 17:11:25 +00003994 } else if (Access->isOriginalAnyPHIKind() && Access->isWrite()) {
3995 auto &Incomings = PHIIncomingAccs[Access->getScopArrayInfo()];
Michael Kruse7de61662018-04-09 23:13:01 +00003996 auto NewEnd = std::remove(Incomings.begin(), Incomings.end(), Access);
3997 Incomings.erase(NewEnd, Incomings.end());
Michael Kruse8b805802017-07-19 17:11:25 +00003998 }
3999}
4000
4001MemoryAccess *Scop::getValueDef(const ScopArrayInfo *SAI) const {
4002 assert(SAI->isValueKind());
4003
4004 Instruction *Val = dyn_cast<Instruction>(SAI->getBasePtr());
4005 if (!Val)
4006 return nullptr;
4007
Michael Kruse6d7a7892017-09-21 14:23:11 +00004008 return ValueDefAccs.lookup(Val);
Michael Kruse8b805802017-07-19 17:11:25 +00004009}
4010
4011ArrayRef<MemoryAccess *> Scop::getValueUses(const ScopArrayInfo *SAI) const {
4012 assert(SAI->isValueKind());
4013 auto It = ValueUseAccs.find(SAI);
4014 if (It == ValueUseAccs.end())
4015 return {};
4016 return It->second;
4017}
4018
4019MemoryAccess *Scop::getPHIRead(const ScopArrayInfo *SAI) const {
4020 assert(SAI->isPHIKind() || SAI->isExitPHIKind());
4021
4022 if (SAI->isExitPHIKind())
4023 return nullptr;
4024
4025 PHINode *PHI = cast<PHINode>(SAI->getBasePtr());
Michael Kruse6d7a7892017-09-21 14:23:11 +00004026 return PHIReadAccs.lookup(PHI);
Michael Kruse8b805802017-07-19 17:11:25 +00004027}
4028
4029ArrayRef<MemoryAccess *> Scop::getPHIIncomings(const ScopArrayInfo *SAI) const {
4030 assert(SAI->isPHIKind() || SAI->isExitPHIKind());
4031 auto It = PHIIncomingAccs.find(SAI);
4032 if (It == PHIIncomingAccs.end())
4033 return {};
4034 return It->second;
4035}
4036
Michael Krusea508a4e2017-07-27 14:39:52 +00004037bool Scop::isEscaping(Instruction *Inst) {
4038 assert(contains(Inst) && "The concept of escaping makes only sense for "
4039 "values defined inside the SCoP");
4040
4041 for (Use &Use : Inst->uses()) {
4042 BasicBlock *UserBB = getUseBlock(Use);
4043 if (!contains(UserBB))
4044 return true;
4045
4046 // When the SCoP region exit needs to be simplified, PHIs in the region exit
4047 // move to a new basic block such that its incoming blocks are not in the
4048 // SCoP anymore.
4049 if (hasSingleExitEdge() && isa<PHINode>(Use.getUser()) &&
4050 isExit(cast<PHINode>(Use.getUser())->getParent()))
4051 return true;
4052 }
4053 return false;
4054}
4055
Dominik Adamski588fc9e2019-07-16 21:10:45 +00004056void Scop::incrementNumberOfAliasingAssumptions(unsigned step) {
4057 AssumptionsAliasing += step;
4058}
4059
Michael Kruse06ed5292017-08-23 13:50:30 +00004060Scop::ScopStatistics Scop::getStatistics() const {
4061 ScopStatistics Result;
4062#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
4063 auto LoopStat = ScopDetection::countBeneficialLoops(&R, *SE, *getLI(), 0);
4064
4065 int NumTotalLoops = LoopStat.NumLoops;
4066 Result.NumBoxedLoops = getBoxedLoops().size();
4067 Result.NumAffineLoops = NumTotalLoops - Result.NumBoxedLoops;
4068
4069 for (const ScopStmt &Stmt : *this) {
4070 isl::set Domain = Stmt.getDomain().intersect_params(getContext());
4071 bool IsInLoop = Stmt.getNumIterators() >= 1;
4072 for (MemoryAccess *MA : Stmt) {
4073 if (!MA->isWrite())
4074 continue;
4075
4076 if (MA->isLatestValueKind()) {
4077 Result.NumValueWrites += 1;
4078 if (IsInLoop)
4079 Result.NumValueWritesInLoops += 1;
4080 }
4081
4082 if (MA->isLatestAnyPHIKind()) {
4083 Result.NumPHIWrites += 1;
4084 if (IsInLoop)
4085 Result.NumPHIWritesInLoops += 1;
4086 }
4087
4088 isl::set AccSet =
4089 MA->getAccessRelation().intersect_domain(Domain).range();
4090 if (AccSet.is_singleton()) {
4091 Result.NumSingletonWrites += 1;
4092 if (IsInLoop)
4093 Result.NumSingletonWritesInLoops += 1;
4094 }
4095 }
4096 }
4097#endif
4098 return Result;
4099}
4100
Eugene Zelenko0c4c2ce2017-08-22 21:25:51 +00004101raw_ostream &polly::operator<<(raw_ostream &OS, const Scop &scop) {
4102 scop.print(OS, PollyPrintInstructions);
4103 return OS;
Michael Krusecd4c9772017-07-21 15:35:53 +00004104}
4105
Johannes Doerfert99191c72016-05-31 09:41:04 +00004106//===----------------------------------------------------------------------===//
4107void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const {
4108 AU.addRequired<LoopInfoWrapperPass>();
4109 AU.addRequired<RegionInfoPass>();
4110 AU.addRequired<DominatorTreeWrapperPass>();
4111 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004112 AU.addRequiredTransitive<ScopDetectionWrapperPass>();
Johannes Doerfert99191c72016-05-31 09:41:04 +00004113 AU.addRequired<AAResultsWrapperPass>();
Michael Kruse89b1f942017-03-17 13:56:53 +00004114 AU.addRequired<AssumptionCacheTracker>();
Michael Krusea4f447c2017-08-28 14:07:33 +00004115 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
Johannes Doerfert99191c72016-05-31 09:41:04 +00004116 AU.setPreservesAll();
4117}
4118
Michael Kruse06ed5292017-08-23 13:50:30 +00004119void updateLoopCountStatistic(ScopDetection::LoopStats Stats,
4120 Scop::ScopStatistics ScopStats) {
4121 assert(Stats.NumLoops == ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops);
4122
4123 NumScops++;
Tobias Grossercd01a362017-02-17 08:12:36 +00004124 NumLoopsInScop += Stats.NumLoops;
4125 MaxNumLoopsInScop =
4126 std::max(MaxNumLoopsInScop.getValue(), (unsigned)Stats.NumLoops);
4127
Tobias Grosserfcc3ad52018-04-18 20:03:36 +00004128 if (Stats.MaxDepth == 0)
4129 NumScopsDepthZero++;
4130 else if (Stats.MaxDepth == 1)
Tobias Grossercd01a362017-02-17 08:12:36 +00004131 NumScopsDepthOne++;
4132 else if (Stats.MaxDepth == 2)
4133 NumScopsDepthTwo++;
4134 else if (Stats.MaxDepth == 3)
4135 NumScopsDepthThree++;
4136 else if (Stats.MaxDepth == 4)
4137 NumScopsDepthFour++;
4138 else if (Stats.MaxDepth == 5)
4139 NumScopsDepthFive++;
4140 else
4141 NumScopsDepthLarger++;
Michael Kruse06ed5292017-08-23 13:50:30 +00004142
4143 NumAffineLoops += ScopStats.NumAffineLoops;
4144 NumBoxedLoops += ScopStats.NumBoxedLoops;
4145
4146 NumValueWrites += ScopStats.NumValueWrites;
4147 NumValueWritesInLoops += ScopStats.NumValueWritesInLoops;
4148 NumPHIWrites += ScopStats.NumPHIWrites;
4149 NumPHIWritesInLoops += ScopStats.NumPHIWritesInLoops;
4150 NumSingletonWrites += ScopStats.NumSingletonWrites;
4151 NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops;
Tobias Grossercd01a362017-02-17 08:12:36 +00004152}
4153
Johannes Doerfert99191c72016-05-31 09:41:04 +00004154bool ScopInfoRegionPass::runOnRegion(Region *R, RGPassManager &RGM) {
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004155 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD();
Johannes Doerfert99191c72016-05-31 09:41:04 +00004156
4157 if (!SD.isMaxRegionInScop(*R))
4158 return false;
4159
4160 Function *F = R->getEntry()->getParent();
4161 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
4162 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
4163 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
4164 auto const &DL = F->getParent()->getDataLayout();
4165 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Michael Kruse89b1f942017-03-17 13:56:53 +00004166 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F);
Michael Krusea4f447c2017-08-28 14:07:33 +00004167 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
Johannes Doerfert99191c72016-05-31 09:41:04 +00004168
Michael Krusea4f447c2017-08-28 14:07:33 +00004169 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE);
Johannes Doerfertb7e97132016-06-27 09:25:40 +00004170 S = SB.getScop(); // take ownership of scop object
Tobias Grossercd01a362017-02-17 08:12:36 +00004171
Michael Kruse06ed5292017-08-23 13:50:30 +00004172#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
Tobias Grossercd01a362017-02-17 08:12:36 +00004173 if (S) {
4174 ScopDetection::LoopStats Stats =
4175 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
Michael Kruse06ed5292017-08-23 13:50:30 +00004176 updateLoopCountStatistic(Stats, S->getStatistics());
Tobias Grossercd01a362017-02-17 08:12:36 +00004177 }
Michael Kruse06ed5292017-08-23 13:50:30 +00004178#endif
Tobias Grossercd01a362017-02-17 08:12:36 +00004179
Tobias Grosser75805372011-04-29 06:27:02 +00004180 return false;
4181}
4182
Johannes Doerfert99191c72016-05-31 09:41:04 +00004183void ScopInfoRegionPass::print(raw_ostream &OS, const Module *) const {
Johannes Doerfertb7e97132016-06-27 09:25:40 +00004184 if (S)
Michael Krusecd4c9772017-07-21 15:35:53 +00004185 S->print(OS, PollyPrintInstructions);
Johannes Doerfertb7e97132016-06-27 09:25:40 +00004186 else
4187 OS << "Invalid Scop!\n";
Johannes Doerfert99191c72016-05-31 09:41:04 +00004188}
Tobias Grosser75805372011-04-29 06:27:02 +00004189
Johannes Doerfert99191c72016-05-31 09:41:04 +00004190char ScopInfoRegionPass::ID = 0;
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00004191
Johannes Doerfert99191c72016-05-31 09:41:04 +00004192Pass *polly::createScopInfoRegionPassPass() { return new ScopInfoRegionPass(); }
4193
4194INITIALIZE_PASS_BEGIN(ScopInfoRegionPass, "polly-scops",
Tobias Grosser73600b82011-10-08 00:30:40 +00004195 "Polly - Create polyhedral description of Scops", false,
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00004196 false);
Chandler Carruth66ef16b2015-09-09 22:13:56 +00004197INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
Michael Kruse89b1f942017-03-17 13:56:53 +00004198INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker);
Chandler Carruthf5579872015-01-17 14:16:56 +00004199INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
Matt Arsenault8ca36812014-07-19 18:40:17 +00004200INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
Tobias Grosserc5bcf242015-08-17 10:57:08 +00004201INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004202INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
Johannes Doerfert96425c22015-08-30 21:13:53 +00004203INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
Johannes Doerfert99191c72016-05-31 09:41:04 +00004204INITIALIZE_PASS_END(ScopInfoRegionPass, "polly-scops",
Tobias Grosser73600b82011-10-08 00:30:40 +00004205 "Polly - Create polyhedral description of Scops", false,
4206 false)
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004207
4208//===----------------------------------------------------------------------===//
Philip Pfaffe838e0882017-05-15 12:55:14 +00004209ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE,
4210 LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT,
Michael Krusea4f447c2017-08-28 14:07:33 +00004211 AssumptionCache &AC, OptimizationRemarkEmitter &ORE)
4212 : DL(DL), SD(SD), SE(SE), LI(LI), AA(AA), DT(DT), AC(AC), ORE(ORE) {
Philip Pfaffef43e7c22017-08-10 07:43:46 +00004213 recompute();
4214}
4215
4216void ScopInfo::recompute() {
4217 RegionToScopMap.clear();
Michael Krusea6d48f52017-06-08 12:06:15 +00004218 /// Create polyhedral description of scops for all the valid regions of a
Philip Pfaffe838e0882017-05-15 12:55:14 +00004219 /// function.
4220 for (auto &It : SD) {
4221 Region *R = const_cast<Region *>(It);
4222 if (!SD.isMaxRegionInScop(*R))
4223 continue;
4224
Michael Krusea4f447c2017-08-28 14:07:33 +00004225 ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE);
Philip Pfaffe838e0882017-05-15 12:55:14 +00004226 std::unique_ptr<Scop> S = SB.getScop();
4227 if (!S)
4228 continue;
Michael Kruse06ed5292017-08-23 13:50:30 +00004229#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
Philip Pfaffeead67db2017-08-02 11:14:41 +00004230 ScopDetection::LoopStats Stats =
4231 ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0);
Michael Kruse06ed5292017-08-23 13:50:30 +00004232 updateLoopCountStatistic(Stats, S->getStatistics());
4233#endif
Philip Pfaffe838e0882017-05-15 12:55:14 +00004234 bool Inserted = RegionToScopMap.insert({R, std::move(S)}).second;
4235 assert(Inserted && "Building Scop for the same region twice!");
4236 (void)Inserted;
4237 }
4238}
4239
Philip Pfaffef43e7c22017-08-10 07:43:46 +00004240bool ScopInfo::invalidate(Function &F, const PreservedAnalyses &PA,
4241 FunctionAnalysisManager::Invalidator &Inv) {
4242 // Check whether the analysis, all analyses on functions have been preserved
4243 // or anything we're holding references to is being invalidated
4244 auto PAC = PA.getChecker<ScopInfoAnalysis>();
4245 return !(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>()) ||
4246 Inv.invalidate<ScopAnalysis>(F, PA) ||
4247 Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
4248 Inv.invalidate<LoopAnalysis>(F, PA) ||
4249 Inv.invalidate<AAManager>(F, PA) ||
4250 Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
4251 Inv.invalidate<AssumptionAnalysis>(F, PA);
4252}
4253
Philip Pfaffe838e0882017-05-15 12:55:14 +00004254AnalysisKey ScopInfoAnalysis::Key;
4255
4256ScopInfoAnalysis::Result ScopInfoAnalysis::run(Function &F,
4257 FunctionAnalysisManager &FAM) {
4258 auto &SD = FAM.getResult<ScopAnalysis>(F);
4259 auto &SE = FAM.getResult<ScalarEvolutionAnalysis>(F);
4260 auto &LI = FAM.getResult<LoopAnalysis>(F);
4261 auto &AA = FAM.getResult<AAManager>(F);
4262 auto &DT = FAM.getResult<DominatorTreeAnalysis>(F);
4263 auto &AC = FAM.getResult<AssumptionAnalysis>(F);
4264 auto &DL = F.getParent()->getDataLayout();
Michael Krusea4f447c2017-08-28 14:07:33 +00004265 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
4266 return {DL, SD, SE, LI, AA, DT, AC, ORE};
Philip Pfaffe838e0882017-05-15 12:55:14 +00004267}
4268
4269PreservedAnalyses ScopInfoPrinterPass::run(Function &F,
4270 FunctionAnalysisManager &FAM) {
4271 auto &SI = FAM.getResult<ScopInfoAnalysis>(F);
Philip Pfaffe96d21432017-08-04 11:28:51 +00004272 // Since the legacy PM processes Scops in bottom up, we print them in reverse
4273 // order here to keep the output persistent
4274 for (auto &It : reverse(SI)) {
Philip Pfaffe838e0882017-05-15 12:55:14 +00004275 if (It.second)
Michael Krusecd4c9772017-07-21 15:35:53 +00004276 It.second->print(Stream, PollyPrintInstructions);
Philip Pfaffe838e0882017-05-15 12:55:14 +00004277 else
4278 Stream << "Invalid Scop!\n";
4279 }
4280 return PreservedAnalyses::all();
4281}
4282
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004283void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
4284 AU.addRequired<LoopInfoWrapperPass>();
4285 AU.addRequired<RegionInfoPass>();
4286 AU.addRequired<DominatorTreeWrapperPass>();
4287 AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004288 AU.addRequiredTransitive<ScopDetectionWrapperPass>();
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004289 AU.addRequired<AAResultsWrapperPass>();
Michael Kruse89b1f942017-03-17 13:56:53 +00004290 AU.addRequired<AssumptionCacheTracker>();
Michael Krusea4f447c2017-08-28 14:07:33 +00004291 AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004292 AU.setPreservesAll();
4293}
4294
4295bool ScopInfoWrapperPass::runOnFunction(Function &F) {
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004296 auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD();
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004297 auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
4298 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
4299 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
4300 auto const &DL = F.getParent()->getDataLayout();
4301 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
Michael Kruse89b1f942017-03-17 13:56:53 +00004302 auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
Michael Krusea4f447c2017-08-28 14:07:33 +00004303 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004304
Michael Krusea4f447c2017-08-28 14:07:33 +00004305 Result.reset(new ScopInfo{DL, SD, SE, LI, AA, DT, AC, ORE});
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004306 return false;
4307}
4308
4309void ScopInfoWrapperPass::print(raw_ostream &OS, const Module *) const {
Philip Pfaffe838e0882017-05-15 12:55:14 +00004310 for (auto &It : *Result) {
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004311 if (It.second)
Michael Krusecd4c9772017-07-21 15:35:53 +00004312 It.second->print(OS, PollyPrintInstructions);
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004313 else
4314 OS << "Invalid Scop!\n";
4315 }
4316}
4317
4318char ScopInfoWrapperPass::ID = 0;
4319
4320Pass *polly::createScopInfoWrapperPassPass() {
4321 return new ScopInfoWrapperPass();
4322}
4323
4324INITIALIZE_PASS_BEGIN(
4325 ScopInfoWrapperPass, "polly-function-scops",
4326 "Polly - Create polyhedral description of all Scops of a function", false,
4327 false);
4328INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass);
Michael Kruse89b1f942017-03-17 13:56:53 +00004329INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker);
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004330INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
4331INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
4332INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
Philip Pfaffe5cc87e32017-05-12 14:37:29 +00004333INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass);
Johannes Doerfert4ba65a52016-06-27 09:32:30 +00004334INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
4335INITIALIZE_PASS_END(
4336 ScopInfoWrapperPass, "polly-function-scops",
4337 "Polly - Create polyhedral description of all Scops of a function", false,
4338 false)