blob: 94e14fd9cdba2961ea6709735ee4fad8cbbc9fc0 [file] [log] [blame]
Tobias Grosser75805372011-04-29 06:27:02 +00001//===--------- ScopInfo.cpp - Create Scops from LLVM IR ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Create a polyhedral description for a static control flow region.
11//
12// The pass creates a polyhedral description of the Scops detected by the Scop
13// detection derived from their LLVM-IR code.
14//
Tobias Grossera5605d32014-10-29 19:58:28 +000015// This representation is shared among several tools in the polyhedral
Tobias Grosser75805372011-04-29 06:27:02 +000016// community, which are e.g. Cloog, Pluto, Loopo, Graphite.
17//
18//===----------------------------------------------------------------------===//
19
Tobias Grosser75805372011-04-29 06:27:02 +000020#include "polly/LinkAllPasses.h"
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000021#include "polly/Options.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000022#include "polly/ScopInfo.h"
Tobias Grosser75805372011-04-29 06:27:02 +000023#include "polly/Support/GICHelper.h"
Tobias Grosser60b54f12011-11-08 15:41:28 +000024#include "polly/Support/SCEVValidator.h"
Tobias Grosser83628182013-05-07 08:11:54 +000025#include "polly/Support/ScopHelper.h"
Sebastian Pop27c10c62013-03-22 22:07:43 +000026#include "polly/TempScopInfo.h"
Tobias Grosserf4c24b22015-04-05 13:11:54 +000027#include "llvm/ADT/MapVector.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000028#include "llvm/ADT/SetVector.h"
Tobias Grosser83628182013-05-07 08:11:54 +000029#include "llvm/ADT/Statistic.h"
Johannes Doerfertecff11d2015-05-22 23:43:58 +000030#include "llvm/ADT/STLExtras.h"
Hongbin Zheng86a37742012-04-25 08:01:38 +000031#include "llvm/ADT/StringExtras.h"
Johannes Doerfertb164c792014-09-18 11:17:17 +000032#include "llvm/Analysis/AliasAnalysis.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000033#include "llvm/Analysis/LoopInfo.h"
Tobias Grosser83628182013-05-07 08:11:54 +000034#include "llvm/Analysis/RegionIterator.h"
35#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Tobias Grosser75805372011-04-29 06:27:02 +000036#include "llvm/Support/Debug.h"
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000037#include "isl/aff.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000038#include "isl/constraint.h"
Tobias Grosserf5338802011-10-06 00:03:35 +000039#include "isl/local_space.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000040#include "isl/map.h"
Tobias Grosser4a8e3562011-12-07 07:42:51 +000041#include "isl/options.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +000042#include "isl/printer.h"
43#include "isl/set.h"
44#include "isl/union_map.h"
Tobias Grossercd524dc2015-05-09 09:36:38 +000045#include "isl/union_set.h"
Tobias Grosseredab1352013-06-21 06:41:31 +000046#include "isl/val.h"
Tobias Grosser75805372011-04-29 06:27:02 +000047#include <sstream>
48#include <string>
49#include <vector>
50
51using namespace llvm;
52using namespace polly;
53
Chandler Carruth95fef942014-04-22 03:30:19 +000054#define DEBUG_TYPE "polly-scops"
55
Tobias Grosser74394f02013-01-14 22:40:23 +000056STATISTIC(ScopFound, "Number of valid Scops");
57STATISTIC(RichScopFound, "Number of Scops containing a loop");
Tobias Grosser75805372011-04-29 06:27:02 +000058
Johannes Doerfert9e7b17b2014-08-18 00:40:13 +000059// Multiplicative reductions can be disabled separately as these kind of
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000060// operations can overflow easily. Additive reductions and bit operations
61// are in contrast pretty stable.
Tobias Grosser483a90d2014-07-09 10:50:10 +000062static cl::opt<bool> DisableMultiplicativeReductions(
63 "polly-disable-multiplicative-reductions",
64 cl::desc("Disable multiplicative reductions"), cl::Hidden, cl::ZeroOrMore,
65 cl::init(false), cl::cat(PollyCategory));
Johannes Doerfert0ee1f212014-06-17 17:31:36 +000066
Johannes Doerfert9143d672014-09-27 11:02:39 +000067static cl::opt<unsigned> RunTimeChecksMaxParameters(
68 "polly-rtc-max-parameters",
69 cl::desc("The maximal number of parameters allowed in RTCs."), cl::Hidden,
70 cl::ZeroOrMore, cl::init(8), cl::cat(PollyCategory));
71
Tobias Grosser71500722015-03-28 15:11:14 +000072static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup(
73 "polly-rtc-max-arrays-per-group",
74 cl::desc("The maximal number of arrays to compare in each alias group."),
75 cl::Hidden, cl::ZeroOrMore, cl::init(20), cl::cat(PollyCategory));
76
Tobias Grosser0695ee42013-09-17 03:30:31 +000077/// Translate a 'const SCEV *' expression in an isl_pw_aff.
Tobias Grosserabfbe632013-02-05 12:09:06 +000078struct SCEVAffinator : public SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
Tobias Grosser0695ee42013-09-17 03:30:31 +000079public:
Tobias Grosser0695ee42013-09-17 03:30:31 +000080 /// @brief Translate a 'const SCEV *' to an isl_pw_aff.
81 ///
82 /// @param Stmt The location at which the scalar evolution expression
83 /// is evaluated.
84 /// @param Expr The expression that is translated.
85 static __isl_give isl_pw_aff *getPwAff(ScopStmt *Stmt, const SCEV *Expr);
86
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000087private:
Tobias Grosser3cc99742012-06-06 16:33:15 +000088 isl_ctx *Ctx;
Tobias Grosserf5338802011-10-06 00:03:35 +000089 int NbLoopSpaces;
Tobias Grosser3cc99742012-06-06 16:33:15 +000090 const Scop *S;
Tobias Grosser33ba62ad2011-08-18 06:31:50 +000091
Tobias Grosser0695ee42013-09-17 03:30:31 +000092 SCEVAffinator(const ScopStmt *Stmt);
93 int getLoopDepth(const Loop *L);
Tobias Grosser60b54f12011-11-08 15:41:28 +000094
Tobias Grosser0695ee42013-09-17 03:30:31 +000095 __isl_give isl_pw_aff *visit(const SCEV *Expr);
96 __isl_give isl_pw_aff *visitConstant(const SCEVConstant *Expr);
97 __isl_give isl_pw_aff *visitTruncateExpr(const SCEVTruncateExpr *Expr);
98 __isl_give isl_pw_aff *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr);
99 __isl_give isl_pw_aff *visitSignExtendExpr(const SCEVSignExtendExpr *Expr);
100 __isl_give isl_pw_aff *visitAddExpr(const SCEVAddExpr *Expr);
101 __isl_give isl_pw_aff *visitMulExpr(const SCEVMulExpr *Expr);
102 __isl_give isl_pw_aff *visitUDivExpr(const SCEVUDivExpr *Expr);
103 __isl_give isl_pw_aff *visitAddRecExpr(const SCEVAddRecExpr *Expr);
104 __isl_give isl_pw_aff *visitSMaxExpr(const SCEVSMaxExpr *Expr);
105 __isl_give isl_pw_aff *visitUMaxExpr(const SCEVUMaxExpr *Expr);
106 __isl_give isl_pw_aff *visitUnknown(const SCEVUnknown *Expr);
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000107 __isl_give isl_pw_aff *visitSDivInstruction(Instruction *SDiv);
Tobias Grosser50165ff2015-06-24 04:13:29 +0000108 __isl_give isl_pw_aff *visitSRemInstruction(Instruction *SDiv);
Tobias Grosser60b54f12011-11-08 15:41:28 +0000109
Tobias Grosser0695ee42013-09-17 03:30:31 +0000110 friend struct SCEVVisitor<SCEVAffinator, isl_pw_aff *>;
111};
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000112
Tobias Grosser0695ee42013-09-17 03:30:31 +0000113SCEVAffinator::SCEVAffinator(const ScopStmt *Stmt)
114 : Ctx(Stmt->getIslCtx()), NbLoopSpaces(Stmt->getNumIterators()),
115 S(Stmt->getParent()) {}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000116
Tobias Grosser0695ee42013-09-17 03:30:31 +0000117__isl_give isl_pw_aff *SCEVAffinator::getPwAff(ScopStmt *Stmt,
118 const SCEV *Scev) {
119 Scop *S = Stmt->getParent();
120 const Region *Reg = &S->getRegion();
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000121
Tobias Grosser0695ee42013-09-17 03:30:31 +0000122 S->addParams(getParamsInAffineExpr(Reg, Scev, *S->getSE()));
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000123
Tobias Grosser0695ee42013-09-17 03:30:31 +0000124 SCEVAffinator Affinator(Stmt);
125 return Affinator.visit(Scev);
126}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000127
Tobias Grosser0695ee42013-09-17 03:30:31 +0000128__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
129 // In case the scev is a valid parameter, we do not further analyze this
130 // expression, but create a new parameter in the isl_pw_aff. This allows us
131 // to treat subexpressions that we cannot translate into an piecewise affine
132 // expression, as constant parameters of the piecewise affine expression.
133 if (isl_id *Id = S->getIdForParam(Expr)) {
134 isl_space *Space = isl_space_set_alloc(Ctx, 1, NbLoopSpaces);
135 Space = isl_space_set_dim_id(Space, isl_dim_param, 0, Id);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000136
Tobias Grosser0695ee42013-09-17 03:30:31 +0000137 isl_set *Domain = isl_set_universe(isl_space_copy(Space));
138 isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
139 Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000140
141 return isl_pw_aff_alloc(Domain, Affine);
142 }
143
Tobias Grosser0695ee42013-09-17 03:30:31 +0000144 return SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr);
145}
146
Tobias Grosser0d170132013-10-03 13:09:19 +0000147__isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
Tobias Grosser0695ee42013-09-17 03:30:31 +0000148 ConstantInt *Value = Expr->getValue();
149 isl_val *v;
150
151 // LLVM does not define if an integer value is interpreted as a signed or
152 // unsigned value. Hence, without further information, it is unknown how
153 // this value needs to be converted to GMP. At the moment, we only support
154 // signed operations. So we just interpret it as signed. Later, there are
155 // two options:
156 //
157 // 1. We always interpret any value as signed and convert the values on
158 // demand.
159 // 2. We pass down the signedness of the calculation and use it to interpret
160 // this constant correctly.
161 v = isl_valFromAPInt(Ctx, Value->getValue(), /* isSigned */ true);
162
163 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
Johannes Doerfert9c147372014-11-19 15:36:59 +0000164 isl_local_space *ls = isl_local_space_from_space(Space);
165 return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v));
Tobias Grosser0695ee42013-09-17 03:30:31 +0000166}
167
168__isl_give isl_pw_aff *
169SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
170 llvm_unreachable("SCEVTruncateExpr not yet supported");
171}
172
173__isl_give isl_pw_aff *
174SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
175 llvm_unreachable("SCEVZeroExtendExpr not yet supported");
176}
177
178__isl_give isl_pw_aff *
179SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
180 // Assuming the value is signed, a sign extension is basically a noop.
181 // TODO: Reconsider this as soon as we support unsigned values.
182 return visit(Expr->getOperand());
183}
184
185__isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
186 isl_pw_aff *Sum = visit(Expr->getOperand(0));
187
188 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
189 isl_pw_aff *NextSummand = visit(Expr->getOperand(i));
190 Sum = isl_pw_aff_add(Sum, NextSummand);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000191 }
192
Tobias Grosser0695ee42013-09-17 03:30:31 +0000193 // TODO: Check for NSW and NUW.
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000194
Tobias Grosser0695ee42013-09-17 03:30:31 +0000195 return Sum;
196}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000197
Tobias Grosser0695ee42013-09-17 03:30:31 +0000198__isl_give isl_pw_aff *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
Johannes Doerfertbe409962015-03-29 20:45:09 +0000199 // Divide Expr into a constant part and the rest. Then visit both and multiply
200 // the result to obtain the representation for Expr. While the second part of
201 // ConstantAndLeftOverPair might still be a SCEVMulExpr we will not get to
202 // this point again. The reason is that if it is a multiplication it consists
203 // only of parameters and we will stop in the visit(const SCEV *) function and
204 // return the isl_pw_aff for that parameter.
205 auto ConstantAndLeftOverPair = extractConstantFactor(Expr, *S->getSE());
206 return isl_pw_aff_mul(visit(ConstantAndLeftOverPair.first),
207 visit(ConstantAndLeftOverPair.second));
Tobias Grosser0695ee42013-09-17 03:30:31 +0000208}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000209
Tobias Grosser0695ee42013-09-17 03:30:31 +0000210__isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
211 llvm_unreachable("SCEVUDivExpr not yet supported");
212}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000213
Tobias Grosser0695ee42013-09-17 03:30:31 +0000214__isl_give isl_pw_aff *
215SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
216 assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000217
Johannes Doerfertd5d8f672015-04-26 19:55:21 +0000218 auto Flags = Expr->getNoWrapFlags();
219
Tobias Grosser0695ee42013-09-17 03:30:31 +0000220 // Directly generate isl_pw_aff for Expr if 'start' is zero.
221 if (Expr->getStart()->isZero()) {
222 assert(S->getRegion().contains(Expr->getLoop()) &&
223 "Scop does not contain the loop referenced in this AddRec");
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000224
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000225 isl_pw_aff *Start = visit(Expr->getStart());
Tobias Grosser0695ee42013-09-17 03:30:31 +0000226 isl_pw_aff *Step = visit(Expr->getOperand(1));
227 isl_space *Space = isl_space_set_alloc(Ctx, 0, NbLoopSpaces);
228 isl_local_space *LocalSpace = isl_local_space_from_space(Space);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000229
Tobias Grosser0695ee42013-09-17 03:30:31 +0000230 int loopDimension = getLoopDepth(Expr->getLoop());
231
232 isl_aff *LAff = isl_aff_set_coefficient_si(
233 isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
234 isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);
235
236 // TODO: Do we need to check for NSW and NUW?
237 return isl_pw_aff_add(Start, isl_pw_aff_mul(Step, LPwAff));
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000238 }
239
Tobias Grosser0695ee42013-09-17 03:30:31 +0000240 // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
241 // if 'start' is not zero.
Johannes Doerfertd5d8f672015-04-26 19:55:21 +0000242 // TODO: Using the original SCEV no-wrap flags is not always safe, however
243 // as our code generation is reordering the expression anyway it doesn't
244 // really matter.
Tobias Grosser0695ee42013-09-17 03:30:31 +0000245 ScalarEvolution &SE = *S->getSE();
Johannes Doerfertd5d8f672015-04-26 19:55:21 +0000246 const SCEV *ZeroStartExpr =
247 SE.getAddRecExpr(SE.getConstant(Expr->getStart()->getType(), 0),
248 Expr->getStepRecurrence(SE), Expr->getLoop(), Flags);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000249
Tobias Grosser0695ee42013-09-17 03:30:31 +0000250 isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr);
251 isl_pw_aff *Start = visit(Expr->getStart());
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000252
Tobias Grosser0695ee42013-09-17 03:30:31 +0000253 return isl_pw_aff_add(ZeroStartResult, Start);
254}
255
256__isl_give isl_pw_aff *SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) {
257 isl_pw_aff *Max = visit(Expr->getOperand(0));
258
259 for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
260 isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
261 Max = isl_pw_aff_max(Max, NextOperand);
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000262 }
263
Tobias Grosser0695ee42013-09-17 03:30:31 +0000264 return Max;
265}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000266
Tobias Grosser0695ee42013-09-17 03:30:31 +0000267__isl_give isl_pw_aff *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
268 llvm_unreachable("SCEVUMaxExpr not yet supported");
269}
270
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000271__isl_give isl_pw_aff *SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
272 assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!");
273 auto *SE = S->getSE();
274
275 auto *Divisor = SDiv->getOperand(1);
276 auto *DivisorSCEV = SE->getSCEV(Divisor);
277 auto *DivisorPWA = visit(DivisorSCEV);
278 assert(isa<ConstantInt>(Divisor) &&
279 "SDiv is no parameter but has a non-constant RHS.");
280
281 auto *Dividend = SDiv->getOperand(0);
282 auto *DividendSCEV = SE->getSCEV(Dividend);
283 auto *DividendPWA = visit(DividendSCEV);
284 return isl_pw_aff_tdiv_q(DividendPWA, DivisorPWA);
285}
286
Tobias Grosser50165ff2015-06-24 04:13:29 +0000287__isl_give isl_pw_aff *SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
288 assert(SRem->getOpcode() == Instruction::SRem && "Assumed SRem instruction!");
289 auto *SE = S->getSE();
290
291 auto *Divisor = dyn_cast<ConstantInt>(SRem->getOperand(1));
292 assert(Divisor && "SRem is no parameter but has a non-constant RHS.");
293 auto *DivisorVal = isl_valFromAPInt(Ctx, Divisor->getValue(),
294 /* isSigned */ true);
295
296 auto *Dividend = SRem->getOperand(0);
297 auto *DividendSCEV = SE->getSCEV(Dividend);
298 auto *DividendPWA = visit(DividendSCEV);
299
300 return isl_pw_aff_mod_val(DividendPWA, isl_val_abs(DivisorVal));
301}
302
Tobias Grosser0695ee42013-09-17 03:30:31 +0000303__isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000304 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
305 switch (I->getOpcode()) {
306 case Instruction::SDiv:
307 return visitSDivInstruction(I);
Tobias Grosser50165ff2015-06-24 04:13:29 +0000308 case Instruction::SRem:
309 return visitSRemInstruction(I);
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000310 default:
311 break; // Fall through.
312 }
313 }
314
315 llvm_unreachable(
316 "Unknowns SCEV was neither parameter nor a valid instruction.");
Tobias Grosser0695ee42013-09-17 03:30:31 +0000317}
318
319int SCEVAffinator::getLoopDepth(const Loop *L) {
320 Loop *outerLoop = S->getRegion().outermostLoopInRegion(const_cast<Loop *>(L));
321 assert(outerLoop && "Scop does not contain this loop");
322 return L->getLoopDepth() - outerLoop->getLoopDepth();
323}
Tobias Grosser33ba62ad2011-08-18 06:31:50 +0000324
Johannes Doerferte7044942015-02-24 11:58:30 +0000325/// @brief Add the bounds of @p Range to the set @p S for dimension @p dim.
326static __isl_give isl_set *addRangeBoundsToSet(__isl_take isl_set *S,
327 const ConstantRange &Range,
328 int dim,
329 enum isl_dim_type type) {
330 isl_val *V;
331 isl_ctx *ctx = isl_set_get_ctx(S);
332
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000333 bool useLowerUpperBound = Range.isSignWrappedSet() && !Range.isFullSet();
334 const auto LB = useLowerUpperBound ? Range.getLower() : Range.getSignedMin();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000335 V = isl_valFromAPInt(ctx, LB, true);
Johannes Doerferte7044942015-02-24 11:58:30 +0000336 isl_set *SLB = isl_set_lower_bound_val(isl_set_copy(S), type, dim, V);
337
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000338 const auto UB = useLowerUpperBound ? Range.getUpper() : Range.getSignedMax();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000339 V = isl_valFromAPInt(ctx, UB, true);
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000340 if (useLowerUpperBound)
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000341 V = isl_val_sub_ui(V, 1);
Johannes Doerferte7044942015-02-24 11:58:30 +0000342 isl_set *SUB = isl_set_upper_bound_val(S, type, dim, V);
343
Johannes Doerfert8f8af432015-04-26 20:07:21 +0000344 if (useLowerUpperBound)
Johannes Doerferte7044942015-02-24 11:58:30 +0000345 return isl_set_union(SLB, SUB);
346 else
347 return isl_set_intersect(SLB, SUB);
348}
349
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000350ScopArrayInfo::ScopArrayInfo(Value *BasePtr, Type *ElementType, isl_ctx *Ctx,
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000351 const SmallVector<const SCEV *, 4> &DimensionSizes)
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000352 : BasePtr(BasePtr), ElementType(ElementType),
353 DimensionSizes(DimensionSizes) {
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000354 const std::string BasePtrName = getIslCompatibleName("MemRef_", BasePtr, "");
355 Id = isl_id_alloc(Ctx, BasePtrName.c_str(), this);
356}
357
358ScopArrayInfo::~ScopArrayInfo() { isl_id_free(Id); }
359
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000360std::string ScopArrayInfo::getName() const { return isl_id_get_name(Id); }
361
362int ScopArrayInfo::getElemSizeInBytes() const {
363 return ElementType->getPrimitiveSizeInBits() / 8;
364}
365
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000366isl_id *ScopArrayInfo::getBasePtrId() const { return isl_id_copy(Id); }
367
368void ScopArrayInfo::dump() const { print(errs()); }
369
370void ScopArrayInfo::print(raw_ostream &OS) const {
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000371 OS.indent(8) << *getElementType() << " " << getName() << "[*]";
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000372 for (unsigned u = 0; u < getNumberOfDimensions(); u++)
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000373 OS << "[" << *DimensionSizes[u] << "]";
374 OS << " // Element size " << getElemSizeInBytes() << "\n";
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000375}
376
377const ScopArrayInfo *
378ScopArrayInfo::getFromAccessFunction(__isl_keep isl_pw_multi_aff *PMA) {
379 isl_id *Id = isl_pw_multi_aff_get_tuple_id(PMA, isl_dim_out);
380 assert(Id && "Output dimension didn't have an ID");
381 return getFromId(Id);
382}
383
384const ScopArrayInfo *ScopArrayInfo::getFromId(isl_id *Id) {
385 void *User = isl_id_get_user(Id);
386 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
387 isl_id_free(Id);
388 return SAI;
389}
390
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000391const std::string
392MemoryAccess::getReductionOperatorStr(MemoryAccess::ReductionType RT) {
393 switch (RT) {
394 case MemoryAccess::RT_NONE:
395 llvm_unreachable("Requested a reduction operator string for a memory "
396 "access which isn't a reduction");
397 case MemoryAccess::RT_ADD:
398 return "+";
399 case MemoryAccess::RT_MUL:
400 return "*";
401 case MemoryAccess::RT_BOR:
402 return "|";
403 case MemoryAccess::RT_BXOR:
404 return "^";
405 case MemoryAccess::RT_BAND:
406 return "&";
407 }
408 llvm_unreachable("Unknown reduction type");
409 return "";
410}
411
Johannes Doerfertf6183392014-07-01 20:52:51 +0000412/// @brief Return the reduction type for a given binary operator
413static MemoryAccess::ReductionType getReductionType(const BinaryOperator *BinOp,
414 const Instruction *Load) {
415 if (!BinOp)
416 return MemoryAccess::RT_NONE;
417 switch (BinOp->getOpcode()) {
418 case Instruction::FAdd:
419 if (!BinOp->hasUnsafeAlgebra())
420 return MemoryAccess::RT_NONE;
421 // Fall through
422 case Instruction::Add:
423 return MemoryAccess::RT_ADD;
424 case Instruction::Or:
425 return MemoryAccess::RT_BOR;
426 case Instruction::Xor:
427 return MemoryAccess::RT_BXOR;
428 case Instruction::And:
429 return MemoryAccess::RT_BAND;
430 case Instruction::FMul:
431 if (!BinOp->hasUnsafeAlgebra())
432 return MemoryAccess::RT_NONE;
433 // Fall through
434 case Instruction::Mul:
435 if (DisableMultiplicativeReductions)
436 return MemoryAccess::RT_NONE;
437 return MemoryAccess::RT_MUL;
438 default:
439 return MemoryAccess::RT_NONE;
440 }
441}
Tobias Grosser75805372011-04-29 06:27:02 +0000442//===----------------------------------------------------------------------===//
443
444MemoryAccess::~MemoryAccess() {
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000445 isl_id_free(Id);
Tobias Grosser54a86e62011-08-18 06:31:46 +0000446 isl_map_free(AccessRelation);
Raghesh Aloor129e8672011-08-15 02:33:39 +0000447 isl_map_free(newAccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000448}
449
Johannes Doerfert8f7124c2014-09-12 11:00:49 +0000450static MemoryAccess::AccessType getMemoryAccessType(const IRAccess &Access) {
451 switch (Access.getType()) {
452 case IRAccess::READ:
453 return MemoryAccess::READ;
454 case IRAccess::MUST_WRITE:
455 return MemoryAccess::MUST_WRITE;
456 case IRAccess::MAY_WRITE:
457 return MemoryAccess::MAY_WRITE;
458 }
459 llvm_unreachable("Unknown IRAccess type!");
460}
461
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000462const ScopArrayInfo *MemoryAccess::getScopArrayInfo() const {
463 isl_id *ArrayId = getArrayId();
464 void *User = isl_id_get_user(ArrayId);
465 const ScopArrayInfo *SAI = static_cast<ScopArrayInfo *>(User);
466 isl_id_free(ArrayId);
467 return SAI;
468}
469
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000470__isl_give isl_id *MemoryAccess::getArrayId() const {
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000471 return isl_map_get_tuple_id(AccessRelation, isl_dim_out);
472}
473
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000474__isl_give isl_pw_multi_aff *MemoryAccess::applyScheduleToAccessRelation(
475 __isl_take isl_union_map *USchedule) const {
Johannes Doerferta99130f2014-10-13 12:58:03 +0000476 isl_map *Schedule, *ScheduledAccRel;
477 isl_union_set *UDomain;
478
479 UDomain = isl_union_set_from_set(getStatement()->getDomain());
480 USchedule = isl_union_map_intersect_domain(USchedule, UDomain);
481 Schedule = isl_map_from_union_map(USchedule);
482 ScheduledAccRel = isl_map_apply_domain(getAccessRelation(), Schedule);
483 return isl_pw_multi_aff_from_map(ScheduledAccRel);
484}
485
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000486__isl_give isl_map *MemoryAccess::getOriginalAccessRelation() const {
Tobias Grosser5d453812011-10-06 00:04:11 +0000487 return isl_map_copy(AccessRelation);
488}
489
Johannes Doerferta99130f2014-10-13 12:58:03 +0000490std::string MemoryAccess::getOriginalAccessRelationStr() const {
Tobias Grosser5d453812011-10-06 00:04:11 +0000491 return stringFromIslObj(AccessRelation);
492}
493
Johannes Doerferta99130f2014-10-13 12:58:03 +0000494__isl_give isl_space *MemoryAccess::getOriginalAccessRelationSpace() const {
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000495 return isl_map_get_space(AccessRelation);
496}
497
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000498__isl_give isl_map *MemoryAccess::getNewAccessRelation() const {
Tobias Grosser5d453812011-10-06 00:04:11 +0000499 return isl_map_copy(newAccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000500}
501
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000502__isl_give isl_basic_map *
503MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
Tobias Grosser084d8f72012-05-29 09:29:44 +0000504 isl_space *Space = isl_space_set_alloc(Statement->getIslCtx(), 0, 1);
Tobias Grossered295662012-09-11 13:50:21 +0000505 Space = isl_space_align_params(Space, Statement->getDomainSpace());
Tobias Grosser75805372011-04-29 06:27:02 +0000506
Tobias Grosser084d8f72012-05-29 09:29:44 +0000507 return isl_basic_map_from_domain_and_range(
Tobias Grosserabfbe632013-02-05 12:09:06 +0000508 isl_basic_set_universe(Statement->getDomainSpace()),
509 isl_basic_set_universe(Space));
Tobias Grosser75805372011-04-29 06:27:02 +0000510}
511
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000512// Formalize no out-of-bound access assumption
513//
514// When delinearizing array accesses we optimistically assume that the
515// delinearized accesses do not access out of bound locations (the subscript
516// expression of each array evaluates for each statement instance that is
517// executed to a value that is larger than zero and strictly smaller than the
518// size of the corresponding dimension). The only exception is the outermost
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000519// dimension for which we do not need to assume any upper bound. At this point
520// we formalize this assumption to ensure that at code generation time the
521// relevant run-time checks can be generated.
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000522//
523// To find the set of constraints necessary to avoid out of bound accesses, we
524// first build the set of data locations that are not within array bounds. We
525// then apply the reverse access relation to obtain the set of iterations that
526// may contain invalid accesses and reduce this set of iterations to the ones
527// that are actually executed by intersecting them with the domain of the
528// statement. If we now project out all loop dimensions, we obtain a set of
529// parameters that may cause statement instances to be executed that may
530// possibly yield out of bound memory accesses. The complement of these
531// constraints is the set of constraints that needs to be assumed to ensure such
532// statement instances are never executed.
533void MemoryAccess::assumeNoOutOfBound(const IRAccess &Access) {
Johannes Doerferta99130f2014-10-13 12:58:03 +0000534 isl_space *Space = isl_space_range(getOriginalAccessRelationSpace());
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000535 isl_set *Outside = isl_set_empty(isl_space_copy(Space));
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000536 for (int i = 1, Size = Access.Subscripts.size(); i < Size; ++i) {
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000537 isl_local_space *LS = isl_local_space_from_space(isl_space_copy(Space));
538 isl_pw_aff *Var =
539 isl_pw_aff_var_on_domain(isl_local_space_copy(LS), isl_dim_set, i);
540 isl_pw_aff *Zero = isl_pw_aff_zero_on_domain(LS);
541
542 isl_set *DimOutside;
543
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000544 DimOutside = isl_pw_aff_lt_set(isl_pw_aff_copy(Var), Zero);
545 isl_pw_aff *SizeE = SCEVAffinator::getPwAff(Statement, Access.Sizes[i - 1]);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000546
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000547 SizeE = isl_pw_aff_drop_dims(SizeE, isl_dim_in, 0,
548 Statement->getNumIterators());
549 SizeE = isl_pw_aff_add_dims(SizeE, isl_dim_in,
550 isl_space_dim(Space, isl_dim_set));
551 SizeE = isl_pw_aff_set_tuple_id(SizeE, isl_dim_in,
552 isl_space_get_tuple_id(Space, isl_dim_set));
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000553
Tobias Grosserf57d63f2014-08-03 21:07:30 +0000554 DimOutside = isl_set_union(DimOutside, isl_pw_aff_le_set(SizeE, Var));
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000555
556 Outside = isl_set_union(Outside, DimOutside);
557 }
558
559 Outside = isl_set_apply(Outside, isl_map_reverse(getAccessRelation()));
560 Outside = isl_set_intersect(Outside, Statement->getDomain());
561 Outside = isl_set_params(Outside);
Tobias Grosserf54bb772015-06-26 12:09:28 +0000562
563 // Remove divs to avoid the construction of overly complicated assumptions.
564 // Doing so increases the set of parameter combinations that are assumed to
565 // not appear. This is always save, but may make the resulting run-time check
566 // bail out more often than strictly necessary.
567 Outside = isl_set_remove_divs(Outside);
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000568 Outside = isl_set_complement(Outside);
569 Statement->getParent()->addAssumption(Outside);
570 isl_space_free(Space);
571}
572
Johannes Doerferte7044942015-02-24 11:58:30 +0000573void MemoryAccess::computeBoundsOnAccessRelation(unsigned ElementSize) {
574 ScalarEvolution *SE = Statement->getParent()->getSE();
575
576 Value *Ptr = getPointerOperand(*getAccessInstruction());
577 if (!Ptr || !SE->isSCEVable(Ptr->getType()))
578 return;
579
580 auto *PtrSCEV = SE->getSCEV(Ptr);
581 if (isa<SCEVCouldNotCompute>(PtrSCEV))
582 return;
583
584 auto *BasePtrSCEV = SE->getPointerBase(PtrSCEV);
585 if (BasePtrSCEV && !isa<SCEVCouldNotCompute>(BasePtrSCEV))
586 PtrSCEV = SE->getMinusSCEV(PtrSCEV, BasePtrSCEV);
587
588 const ConstantRange &Range = SE->getSignedRange(PtrSCEV);
589 if (Range.isFullSet())
590 return;
591
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000592 bool isWrapping = Range.isSignWrappedSet();
Johannes Doerferte7044942015-02-24 11:58:30 +0000593 unsigned BW = Range.getBitWidth();
Johannes Doerferte4bd53b2015-03-08 19:49:50 +0000594 const auto LB = isWrapping ? Range.getLower() : Range.getSignedMin();
595 const auto UB = isWrapping ? Range.getUpper() : Range.getSignedMax();
596
597 auto Min = LB.sdiv(APInt(BW, ElementSize));
598 auto Max = (UB - APInt(BW, 1)).sdiv(APInt(BW, ElementSize));
Johannes Doerferte7044942015-02-24 11:58:30 +0000599
600 isl_set *AccessRange = isl_map_range(isl_map_copy(AccessRelation));
601 AccessRange =
602 addRangeBoundsToSet(AccessRange, ConstantRange(Min, Max), 0, isl_dim_set);
603 AccessRelation = isl_map_intersect_range(AccessRelation, AccessRange);
604}
605
Tobias Grosser619190d2015-03-30 17:22:28 +0000606__isl_give isl_map *MemoryAccess::foldAccess(const IRAccess &Access,
607 __isl_take isl_map *AccessRelation,
608 ScopStmt *Statement) {
609 int Size = Access.Subscripts.size();
610
611 for (int i = Size - 2; i >= 0; --i) {
612 isl_space *Space;
613 isl_map *MapOne, *MapTwo;
614 isl_pw_aff *DimSize = SCEVAffinator::getPwAff(Statement, Access.Sizes[i]);
615
616 isl_space *SpaceSize = isl_pw_aff_get_space(DimSize);
617 isl_pw_aff_free(DimSize);
618 isl_id *ParamId = isl_space_get_dim_id(SpaceSize, isl_dim_param, 0);
619
620 Space = isl_map_get_space(AccessRelation);
621 Space = isl_space_map_from_set(isl_space_range(Space));
622 Space = isl_space_align_params(Space, SpaceSize);
623
624 int ParamLocation = isl_space_find_dim_by_id(Space, isl_dim_param, ParamId);
625 isl_id_free(ParamId);
626
627 MapOne = isl_map_universe(isl_space_copy(Space));
628 for (int j = 0; j < Size; ++j)
629 MapOne = isl_map_equate(MapOne, isl_dim_in, j, isl_dim_out, j);
630 MapOne = isl_map_lower_bound_si(MapOne, isl_dim_in, i + 1, 0);
631
632 MapTwo = isl_map_universe(isl_space_copy(Space));
633 for (int j = 0; j < Size; ++j)
634 if (j < i || j > i + 1)
635 MapTwo = isl_map_equate(MapTwo, isl_dim_in, j, isl_dim_out, j);
636
637 isl_local_space *LS = isl_local_space_from_space(Space);
638 isl_constraint *C;
639 C = isl_equality_alloc(isl_local_space_copy(LS));
640 C = isl_constraint_set_constant_si(C, -1);
641 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i, 1);
642 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i, -1);
643 MapTwo = isl_map_add_constraint(MapTwo, C);
644 C = isl_equality_alloc(LS);
645 C = isl_constraint_set_coefficient_si(C, isl_dim_in, i + 1, 1);
646 C = isl_constraint_set_coefficient_si(C, isl_dim_out, i + 1, -1);
647 C = isl_constraint_set_coefficient_si(C, isl_dim_param, ParamLocation, 1);
648 MapTwo = isl_map_add_constraint(MapTwo, C);
649 MapTwo = isl_map_upper_bound_si(MapTwo, isl_dim_in, i + 1, -1);
650
651 MapOne = isl_map_union(MapOne, MapTwo);
652 AccessRelation = isl_map_apply_range(AccessRelation, MapOne);
653 }
654 return AccessRelation;
655}
656
Johannes Doerfert13c8cf22014-08-10 08:09:38 +0000657MemoryAccess::MemoryAccess(const IRAccess &Access, Instruction *AccInst,
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000658 ScopStmt *Statement, const ScopArrayInfo *SAI,
659 int Identifier)
Johannes Doerfert4c7ce472014-10-08 10:11:33 +0000660 : AccType(getMemoryAccessType(Access)), Statement(Statement), Inst(AccInst),
Johannes Doerfert8f7124c2014-09-12 11:00:49 +0000661 newAccessRelation(nullptr) {
Tobias Grosser75805372011-04-29 06:27:02 +0000662
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000663 isl_ctx *Ctx = Statement->getIslCtx();
Tobias Grosser9759f852011-11-10 12:44:55 +0000664 BaseAddr = Access.getBase();
Johannes Doerfert79fc23f2014-07-24 23:48:02 +0000665 BaseName = getIslCompatibleName("MemRef_", getBaseAddr(), "");
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000666
667 isl_id *BaseAddrId = SAI->getBasePtrId();
Tobias Grosser5683df42011-11-09 22:34:34 +0000668
Tobias Grossere29d31c2015-05-15 12:24:09 +0000669 auto IdName = "__polly_array_ref_ " + std::to_string(Identifier);
670 Id = isl_id_alloc(Ctx, IdName.c_str(), nullptr);
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000671
Tobias Grossera1879642011-12-20 10:43:14 +0000672 if (!Access.isAffine()) {
Tobias Grosser4f967492013-06-23 05:21:18 +0000673 // We overapproximate non-affine accesses with a possible access to the
674 // whole array. For read accesses it does not make a difference, if an
675 // access must or may happen. However, for write accesses it is important to
676 // differentiate between writes that must happen and writes that may happen.
Tobias Grosser04d6ae62013-06-23 06:04:54 +0000677 AccessRelation = isl_map_from_basic_map(createBasicAccessMap(Statement));
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000678 AccessRelation =
679 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
Johannes Doerferte7044942015-02-24 11:58:30 +0000680
681 computeBoundsOnAccessRelation(Access.getElemSizeInBytes());
Tobias Grossera1879642011-12-20 10:43:14 +0000682 return;
683 }
684
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000685 isl_space *Space = isl_space_alloc(Ctx, 0, Statement->getNumIterators(), 0);
Tobias Grosser79baa212014-04-10 08:38:02 +0000686 AccessRelation = isl_map_universe(Space);
Tobias Grossera1879642011-12-20 10:43:14 +0000687
Tobias Grosser79baa212014-04-10 08:38:02 +0000688 for (int i = 0, Size = Access.Subscripts.size(); i < Size; ++i) {
Sebastian Pop18016682014-04-08 21:20:44 +0000689 isl_pw_aff *Affine =
690 SCEVAffinator::getPwAff(Statement, Access.Subscripts[i]);
Tobias Grosser75805372011-04-29 06:27:02 +0000691
Sebastian Pop422e33f2014-06-03 18:16:31 +0000692 if (Size == 1) {
693 // For the non delinearized arrays, divide the access function of the last
694 // subscript by the size of the elements in the array.
Sebastian Pop18016682014-04-08 21:20:44 +0000695 //
696 // A stride one array access in C expressed as A[i] is expressed in
697 // LLVM-IR as something like A[i * elementsize]. This hides the fact that
698 // two subsequent values of 'i' index two values that are stored next to
699 // each other in memory. By this division we make this characteristic
700 // obvious again.
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000701 isl_val *v = isl_val_int_from_si(Ctx, Access.getElemSizeInBytes());
Sebastian Pop18016682014-04-08 21:20:44 +0000702 Affine = isl_pw_aff_scale_down_val(Affine, v);
703 }
704
705 isl_map *SubscriptMap = isl_map_from_pw_aff(Affine);
706
Tobias Grosser79baa212014-04-10 08:38:02 +0000707 AccessRelation = isl_map_flat_range_product(AccessRelation, SubscriptMap);
Sebastian Pop18016682014-04-08 21:20:44 +0000708 }
709
Tobias Grosser619190d2015-03-30 17:22:28 +0000710 AccessRelation = foldAccess(Access, AccessRelation, Statement);
711
Tobias Grosser79baa212014-04-10 08:38:02 +0000712 Space = Statement->getDomainSpace();
Tobias Grosserabfbe632013-02-05 12:09:06 +0000713 AccessRelation = isl_map_set_tuple_id(
714 AccessRelation, isl_dim_in, isl_space_get_tuple_id(Space, isl_dim_set));
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000715 AccessRelation =
716 isl_map_set_tuple_id(AccessRelation, isl_dim_out, BaseAddrId);
717
Tobias Grosser5e6813d2014-07-02 17:47:48 +0000718 assumeNoOutOfBound(Access);
Tobias Grosseraa660a92015-03-30 00:07:50 +0000719 AccessRelation = isl_map_gist_domain(AccessRelation, Statement->getDomain());
Johannes Doerfert5d83f092014-07-29 08:37:55 +0000720 isl_space_free(Space);
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000721}
Tobias Grosser30b8a092011-08-18 07:51:37 +0000722
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000723void MemoryAccess::realignParams() {
Tobias Grosser6defb5b2014-04-10 08:37:44 +0000724 isl_space *ParamSpace = Statement->getParent()->getParamSpace();
Tobias Grosser37487052011-10-06 00:03:42 +0000725 AccessRelation = isl_map_align_params(AccessRelation, ParamSpace);
Tobias Grosser75805372011-04-29 06:27:02 +0000726}
727
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000728const std::string MemoryAccess::getReductionOperatorStr() const {
729 return MemoryAccess::getReductionOperatorStr(getReductionType());
730}
731
Tobias Grosser6f48e0f2015-05-15 09:58:32 +0000732__isl_give isl_id *MemoryAccess::getId() const { return isl_id_copy(Id); }
733
Johannes Doerfertf6183392014-07-01 20:52:51 +0000734raw_ostream &polly::operator<<(raw_ostream &OS,
735 MemoryAccess::ReductionType RT) {
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000736 if (RT == MemoryAccess::RT_NONE)
Johannes Doerfertf6183392014-07-01 20:52:51 +0000737 OS << "NONE";
Johannes Doerfert32868bf2014-08-01 08:13:25 +0000738 else
739 OS << MemoryAccess::getReductionOperatorStr(RT);
Johannes Doerfertf6183392014-07-01 20:52:51 +0000740 return OS;
741}
742
Tobias Grosser75805372011-04-29 06:27:02 +0000743void MemoryAccess::print(raw_ostream &OS) const {
Johannes Doerfert4c7ce472014-10-08 10:11:33 +0000744 switch (AccType) {
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000745 case READ:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000746 OS.indent(12) << "ReadAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000747 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000748 case MUST_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000749 OS.indent(12) << "MustWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000750 break;
Tobias Grosserb58f6a42013-07-13 20:41:24 +0000751 case MAY_WRITE:
Johannes Doerfert6780bc32014-06-26 18:47:03 +0000752 OS.indent(12) << "MayWriteAccess :=\t";
Tobias Grosser4f967492013-06-23 05:21:18 +0000753 break;
754 }
Johannes Doerfert0ff23ec2015-02-06 20:13:15 +0000755 OS << "[Reduction Type: " << getReductionType() << "] ";
756 OS << "[Scalar: " << isScalar() << "]\n";
Johannes Doerferta99130f2014-10-13 12:58:03 +0000757 OS.indent(16) << getOriginalAccessRelationStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +0000758}
759
Tobias Grosser74394f02013-01-14 22:40:23 +0000760void MemoryAccess::dump() const { print(errs()); }
Tobias Grosser75805372011-04-29 06:27:02 +0000761
762// Create a map in the size of the provided set domain, that maps from the
763// one element of the provided set domain to another element of the provided
764// set domain.
765// The mapping is limited to all points that are equal in all but the last
766// dimension and for which the last dimension of the input is strict smaller
767// than the last dimension of the output.
768//
769// getEqualAndLarger(set[i0, i1, ..., iX]):
770//
771// set[i0, i1, ..., iX] -> set[o0, o1, ..., oX]
772// : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1), iX < oX
773//
Tobias Grosserf5338802011-10-06 00:03:35 +0000774static isl_map *getEqualAndLarger(isl_space *setDomain) {
Tobias Grosserc327932c2012-02-01 14:23:36 +0000775 isl_space *Space = isl_space_map_from_set(setDomain);
Tobias Grosser1b6ea572015-05-21 19:02:44 +0000776 isl_map *Map = isl_map_universe(Space);
Sebastian Pop40408762013-10-04 17:14:53 +0000777 unsigned lastDimension = isl_map_dim(Map, isl_dim_in) - 1;
Tobias Grosser75805372011-04-29 06:27:02 +0000778
779 // Set all but the last dimension to be equal for the input and output
780 //
781 // input[i0, i1, ..., iX] -> output[o0, o1, ..., oX]
782 // : i0 = o0, i1 = o1, ..., i(X-1) = o(X-1)
Sebastian Pop40408762013-10-04 17:14:53 +0000783 for (unsigned i = 0; i < lastDimension; ++i)
Tobias Grosserc327932c2012-02-01 14:23:36 +0000784 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i);
Tobias Grosser75805372011-04-29 06:27:02 +0000785
786 // Set the last dimension of the input to be strict smaller than the
787 // last dimension of the output.
788 //
789 // input[?,?,?,...,iX] -> output[?,?,?,...,oX] : iX < oX
Tobias Grosser1b6ea572015-05-21 19:02:44 +0000790 Map = isl_map_order_lt(Map, isl_dim_in, lastDimension, isl_dim_out,
791 lastDimension);
Tobias Grosserc327932c2012-02-01 14:23:36 +0000792 return Map;
Tobias Grosser75805372011-04-29 06:27:02 +0000793}
794
Tobias Grosser4f663aa2015-03-30 11:52:59 +0000795__isl_give isl_set *
796MemoryAccess::getStride(__isl_take const isl_map *Schedule) const {
Tobias Grosserabfbe632013-02-05 12:09:06 +0000797 isl_map *S = const_cast<isl_map *>(Schedule);
Johannes Doerferta99130f2014-10-13 12:58:03 +0000798 isl_map *AccessRelation = getAccessRelation();
Sebastian Popa00a0292012-12-18 07:46:06 +0000799 isl_space *Space = isl_space_range(isl_map_get_space(S));
800 isl_map *NextScatt = getEqualAndLarger(Space);
Tobias Grosser75805372011-04-29 06:27:02 +0000801
Sebastian Popa00a0292012-12-18 07:46:06 +0000802 S = isl_map_reverse(S);
803 NextScatt = isl_map_lexmin(NextScatt);
Tobias Grosser75805372011-04-29 06:27:02 +0000804
Sebastian Popa00a0292012-12-18 07:46:06 +0000805 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(S));
806 NextScatt = isl_map_apply_range(NextScatt, isl_map_copy(AccessRelation));
807 NextScatt = isl_map_apply_domain(NextScatt, S);
808 NextScatt = isl_map_apply_domain(NextScatt, AccessRelation);
Tobias Grosser75805372011-04-29 06:27:02 +0000809
Sebastian Popa00a0292012-12-18 07:46:06 +0000810 isl_set *Deltas = isl_map_deltas(NextScatt);
811 return Deltas;
Tobias Grosser75805372011-04-29 06:27:02 +0000812}
813
Sebastian Popa00a0292012-12-18 07:46:06 +0000814bool MemoryAccess::isStrideX(__isl_take const isl_map *Schedule,
Tobias Grosser28dd4862012-01-24 16:42:16 +0000815 int StrideWidth) const {
816 isl_set *Stride, *StrideX;
817 bool IsStrideX;
Tobias Grosser75805372011-04-29 06:27:02 +0000818
Sebastian Popa00a0292012-12-18 07:46:06 +0000819 Stride = getStride(Schedule);
Tobias Grosser28dd4862012-01-24 16:42:16 +0000820 StrideX = isl_set_universe(isl_set_get_space(Stride));
821 StrideX = isl_set_fix_si(StrideX, isl_dim_set, 0, StrideWidth);
822 IsStrideX = isl_set_is_equal(Stride, StrideX);
Tobias Grosser75805372011-04-29 06:27:02 +0000823
Tobias Grosser28dd4862012-01-24 16:42:16 +0000824 isl_set_free(StrideX);
Tobias Grosserdea98232012-01-17 20:34:27 +0000825 isl_set_free(Stride);
Tobias Grosserb76f38532011-08-20 11:11:25 +0000826
Tobias Grosser28dd4862012-01-24 16:42:16 +0000827 return IsStrideX;
828}
829
Sebastian Popa00a0292012-12-18 07:46:06 +0000830bool MemoryAccess::isStrideZero(const isl_map *Schedule) const {
831 return isStrideX(Schedule, 0);
Tobias Grosser75805372011-04-29 06:27:02 +0000832}
833
Tobias Grosser79baa212014-04-10 08:38:02 +0000834bool MemoryAccess::isScalar() const {
835 return isl_map_n_out(AccessRelation) == 0;
836}
837
Sebastian Popa00a0292012-12-18 07:46:06 +0000838bool MemoryAccess::isStrideOne(const isl_map *Schedule) const {
839 return isStrideX(Schedule, 1);
Tobias Grosser75805372011-04-29 06:27:02 +0000840}
841
Tobias Grosser5d453812011-10-06 00:04:11 +0000842void MemoryAccess::setNewAccessRelation(isl_map *newAccess) {
Tobias Grosserb76f38532011-08-20 11:11:25 +0000843 isl_map_free(newAccessRelation);
Raghesh Aloor7a04f4f2011-08-03 13:47:59 +0000844 newAccessRelation = newAccess;
Raghesh Aloor3cb66282011-07-12 17:14:03 +0000845}
Tobias Grosser75805372011-04-29 06:27:02 +0000846
847//===----------------------------------------------------------------------===//
Tobias Grossercf3942d2011-10-06 00:04:05 +0000848
Tobias Grosser54839312015-04-21 11:37:25 +0000849isl_map *ScopStmt::getSchedule() const { return isl_map_copy(Schedule); }
Tobias Grossercf3942d2011-10-06 00:04:05 +0000850
Tobias Grosser37eb4222014-02-20 21:43:54 +0000851void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
852 assert(isl_set_is_subset(NewDomain, Domain) &&
853 "New domain is not a subset of old domain!");
854 isl_set_free(Domain);
855 Domain = NewDomain;
Tobias Grosser54839312015-04-21 11:37:25 +0000856 Schedule = isl_map_intersect_domain(Schedule, isl_set_copy(Domain));
Tobias Grosser37eb4222014-02-20 21:43:54 +0000857}
858
Tobias Grosser54839312015-04-21 11:37:25 +0000859void ScopStmt::setSchedule(__isl_take isl_map *NewSchedule) {
860 assert(NewSchedule && "New schedule is nullptr");
861 isl_map_free(Schedule);
862 Schedule = NewSchedule;
Tobias Grosserb76f38532011-08-20 11:11:25 +0000863}
864
Tobias Grosser54839312015-04-21 11:37:25 +0000865void ScopStmt::buildSchedule(SmallVectorImpl<unsigned> &ScheduleVec) {
Tobias Grosser78d8a3d2012-01-17 20:34:23 +0000866 unsigned NbIterators = getNumIterators();
Tobias Grosser54839312015-04-21 11:37:25 +0000867 unsigned NbScheduleDims = Parent.getMaxLoopDepth() * 2 + 1;
Tobias Grosser78d8a3d2012-01-17 20:34:23 +0000868
Tobias Grosser54839312015-04-21 11:37:25 +0000869 isl_space *Space = isl_space_set_alloc(getIslCtx(), 0, NbScheduleDims);
Tobias Grosser78d8a3d2012-01-17 20:34:23 +0000870
Tobias Grosser54839312015-04-21 11:37:25 +0000871 Schedule = isl_map_from_domain_and_range(isl_set_universe(getDomainSpace()),
Tobias Grosser654af8f2015-04-21 11:42:01 +0000872 isl_set_universe(Space));
Tobias Grosser75805372011-04-29 06:27:02 +0000873
874 // Loop dimensions.
Tobias Grosser78d8a3d2012-01-17 20:34:23 +0000875 for (unsigned i = 0; i < NbIterators; ++i)
Tobias Grosser654af8f2015-04-21 11:42:01 +0000876 Schedule = isl_map_equate(Schedule, isl_dim_out, 2 * i + 1, isl_dim_in, i);
Tobias Grosser75805372011-04-29 06:27:02 +0000877
878 // Constant dimensions
Tobias Grosser78d8a3d2012-01-17 20:34:23 +0000879 for (unsigned i = 0; i < NbIterators + 1; ++i)
Tobias Grosser54839312015-04-21 11:37:25 +0000880 Schedule = isl_map_fix_si(Schedule, isl_dim_out, 2 * i, ScheduleVec[i]);
Tobias Grosser75805372011-04-29 06:27:02 +0000881
Tobias Grosser54839312015-04-21 11:37:25 +0000882 // Fill schedule dimensions.
883 for (unsigned i = 2 * NbIterators + 1; i < NbScheduleDims; ++i)
884 Schedule = isl_map_fix_si(Schedule, isl_dim_out, i, 0);
Tobias Grosser75805372011-04-29 06:27:02 +0000885
Tobias Grosser54839312015-04-21 11:37:25 +0000886 Schedule = isl_map_align_params(Schedule, Parent.getParamSpace());
Tobias Grosser75805372011-04-29 06:27:02 +0000887}
888
Johannes Doerfertff9d1982015-02-24 12:00:50 +0000889void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
890 bool isApproximated) {
891 AccFuncSetType *AFS = tempScop.getAccessFunctions(Block);
892 if (!AFS)
893 return;
894
895 for (auto &AccessPair : *AFS) {
896 IRAccess &Access = AccessPair.first;
Johannes Doerfert1a28a892014-10-05 11:32:18 +0000897 Instruction *AccessInst = AccessPair.second;
898
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000899 Type *ElementType = getAccessInstType(AccessInst);
Johannes Doerfert80ef1102014-11-07 08:31:31 +0000900 const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
Tobias Grosser49ad36c2015-05-20 08:05:31 +0000901 Access.getBase(), ElementType, Access.Sizes);
Johannes Doerfert80ef1102014-11-07 08:31:31 +0000902
Johannes Doerfertff9d1982015-02-24 12:00:50 +0000903 if (isApproximated && Access.isWrite())
904 Access.setMayWrite();
905
Johannes Doerfertecff11d2015-05-22 23:43:58 +0000906 MemoryAccessList *&MAL = InstructionToAccess[AccessInst];
907 if (!MAL)
908 MAL = new MemoryAccessList();
909 MAL->emplace_front(Access, AccessInst, this, SAI, MemAccs.size());
910 MemAccs.push_back(&MAL->front());
Tobias Grosser75805372011-04-29 06:27:02 +0000911 }
912}
913
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000914void ScopStmt::realignParams() {
Johannes Doerfertf6752892014-06-13 18:01:45 +0000915 for (MemoryAccess *MA : *this)
916 MA->realignParams();
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000917
918 Domain = isl_set_align_params(Domain, Parent.getParamSpace());
Tobias Grosser54839312015-04-21 11:37:25 +0000919 Schedule = isl_map_align_params(Schedule, Parent.getParamSpace());
Tobias Grosser8cae72f2011-11-08 15:41:08 +0000920}
921
Tobias Grosser65b00582011-11-08 15:41:19 +0000922__isl_give isl_set *ScopStmt::buildConditionSet(const Comparison &Comp) {
Tobias Grossera601fbd2011-11-09 22:34:44 +0000923 isl_pw_aff *L = SCEVAffinator::getPwAff(this, Comp.getLHS());
924 isl_pw_aff *R = SCEVAffinator::getPwAff(this, Comp.getRHS());
Tobias Grosser75805372011-04-29 06:27:02 +0000925
Tobias Grosserd2795d02011-08-18 07:51:40 +0000926 switch (Comp.getPred()) {
Tobias Grosser75805372011-04-29 06:27:02 +0000927 case ICmpInst::ICMP_EQ:
Tobias Grosser048c8792011-10-23 20:59:20 +0000928 return isl_pw_aff_eq_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000929 case ICmpInst::ICMP_NE:
Tobias Grosser048c8792011-10-23 20:59:20 +0000930 return isl_pw_aff_ne_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000931 case ICmpInst::ICMP_SLT:
Tobias Grosser048c8792011-10-23 20:59:20 +0000932 return isl_pw_aff_lt_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000933 case ICmpInst::ICMP_SLE:
Tobias Grosser048c8792011-10-23 20:59:20 +0000934 return isl_pw_aff_le_set(L, R);
Tobias Grosserd2795d02011-08-18 07:51:40 +0000935 case ICmpInst::ICMP_SGT:
Tobias Grosser048c8792011-10-23 20:59:20 +0000936 return isl_pw_aff_gt_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000937 case ICmpInst::ICMP_SGE:
Tobias Grosser048c8792011-10-23 20:59:20 +0000938 return isl_pw_aff_ge_set(L, R);
Tobias Grosserd2795d02011-08-18 07:51:40 +0000939 case ICmpInst::ICMP_ULT:
Tobias Grosserbfbc3692015-01-09 00:01:33 +0000940 return isl_pw_aff_lt_set(L, R);
Tobias Grosserd2795d02011-08-18 07:51:40 +0000941 case ICmpInst::ICMP_UGT:
Tobias Grosserbfbc3692015-01-09 00:01:33 +0000942 return isl_pw_aff_gt_set(L, R);
Tobias Grosserd2795d02011-08-18 07:51:40 +0000943 case ICmpInst::ICMP_ULE:
Tobias Grosserbfbc3692015-01-09 00:01:33 +0000944 return isl_pw_aff_le_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000945 case ICmpInst::ICMP_UGE:
Tobias Grosserbfbc3692015-01-09 00:01:33 +0000946 return isl_pw_aff_ge_set(L, R);
Tobias Grosser75805372011-04-29 06:27:02 +0000947 default:
948 llvm_unreachable("Non integer predicate not supported");
949 }
Tobias Grosser75805372011-04-29 06:27:02 +0000950}
951
Tobias Grossere19661e2011-10-07 08:46:57 +0000952__isl_give isl_set *ScopStmt::addLoopBoundsToDomain(__isl_take isl_set *Domain,
Tobias Grosser60b54f12011-11-08 15:41:28 +0000953 TempScop &tempScop) {
Tobias Grossere19661e2011-10-07 08:46:57 +0000954 isl_space *Space;
955 isl_local_space *LocalSpace;
Tobias Grosser75805372011-04-29 06:27:02 +0000956
Tobias Grossere19661e2011-10-07 08:46:57 +0000957 Space = isl_set_get_space(Domain);
958 LocalSpace = isl_local_space_from_space(Space);
Tobias Grosserf5338802011-10-06 00:03:35 +0000959
Johannes Doerfert5ad8a6a2014-11-01 01:14:56 +0000960 ScalarEvolution *SE = getParent()->getSE();
Tobias Grosser75805372011-04-29 06:27:02 +0000961 for (int i = 0, e = getNumIterators(); i != e; ++i) {
Tobias Grosser9b13d3d2011-10-06 22:32:58 +0000962 isl_aff *Zero = isl_aff_zero_on_domain(isl_local_space_copy(LocalSpace));
Tobias Grosserabfbe632013-02-05 12:09:06 +0000963 isl_pw_aff *IV =
964 isl_pw_aff_from_aff(isl_aff_set_coefficient_si(Zero, isl_dim_in, i, 1));
Tobias Grosser75805372011-04-29 06:27:02 +0000965
Tobias Grosser9b13d3d2011-10-06 22:32:58 +0000966 // 0 <= IV.
967 isl_set *LowerBound = isl_pw_aff_nonneg_set(isl_pw_aff_copy(IV));
968 Domain = isl_set_intersect(Domain, LowerBound);
969
970 // IV <= LatchExecutions.
Hongbin Zheng27f3afb2011-04-30 03:26:51 +0000971 const Loop *L = getLoopForDimension(i);
Johannes Doerfert5ad8a6a2014-11-01 01:14:56 +0000972 const SCEV *LatchExecutions = SE->getBackedgeTakenCount(L);
Tobias Grosser9b13d3d2011-10-06 22:32:58 +0000973 isl_pw_aff *UpperBound = SCEVAffinator::getPwAff(this, LatchExecutions);
974 isl_set *UpperBoundSet = isl_pw_aff_le_set(IV, UpperBound);
Tobias Grosser75805372011-04-29 06:27:02 +0000975 Domain = isl_set_intersect(Domain, UpperBoundSet);
976 }
977
Tobias Grosserf5338802011-10-06 00:03:35 +0000978 isl_local_space_free(LocalSpace);
Tobias Grossere19661e2011-10-07 08:46:57 +0000979 return Domain;
Tobias Grosser75805372011-04-29 06:27:02 +0000980}
981
Tobias Grossere602a072013-05-07 07:30:56 +0000982__isl_give isl_set *ScopStmt::addConditionsToDomain(__isl_take isl_set *Domain,
983 TempScop &tempScop,
984 const Region &CurRegion) {
Tobias Grossere19661e2011-10-07 08:46:57 +0000985 const Region *TopRegion = tempScop.getMaxRegion().getParent(),
Tobias Grosserd7e58642013-04-10 06:55:45 +0000986 *CurrentRegion = &CurRegion;
Johannes Doerfertff9d1982015-02-24 12:00:50 +0000987 const BasicBlock *BranchingBB = BB ? BB : R->getEntry();
Tobias Grosser75805372011-04-29 06:27:02 +0000988
Tobias Grosser75805372011-04-29 06:27:02 +0000989 do {
Tobias Grossere19661e2011-10-07 08:46:57 +0000990 if (BranchingBB != CurrentRegion->getEntry()) {
991 if (const BBCond *Condition = tempScop.getBBCond(BranchingBB))
Tobias Grosser083d3d32014-06-28 08:59:45 +0000992 for (const auto &C : *Condition) {
993 isl_set *ConditionSet = buildConditionSet(C);
Tobias Grossere19661e2011-10-07 08:46:57 +0000994 Domain = isl_set_intersect(Domain, ConditionSet);
Tobias Grosser75805372011-04-29 06:27:02 +0000995 }
996 }
Tobias Grossere19661e2011-10-07 08:46:57 +0000997 BranchingBB = CurrentRegion->getEntry();
998 CurrentRegion = CurrentRegion->getParent();
999 } while (TopRegion != CurrentRegion);
Tobias Grosser75805372011-04-29 06:27:02 +00001000
Tobias Grossere19661e2011-10-07 08:46:57 +00001001 return Domain;
Tobias Grosser75805372011-04-29 06:27:02 +00001002}
1003
Tobias Grossere602a072013-05-07 07:30:56 +00001004__isl_give isl_set *ScopStmt::buildDomain(TempScop &tempScop,
1005 const Region &CurRegion) {
Tobias Grossere19661e2011-10-07 08:46:57 +00001006 isl_space *Space;
1007 isl_set *Domain;
Tobias Grosser084d8f72012-05-29 09:29:44 +00001008 isl_id *Id;
Tobias Grossere19661e2011-10-07 08:46:57 +00001009
1010 Space = isl_space_set_alloc(getIslCtx(), 0, getNumIterators());
1011
Tobias Grosser084d8f72012-05-29 09:29:44 +00001012 Id = isl_id_alloc(getIslCtx(), getBaseName(), this);
1013
Tobias Grossere19661e2011-10-07 08:46:57 +00001014 Domain = isl_set_universe(Space);
Tobias Grossere19661e2011-10-07 08:46:57 +00001015 Domain = addLoopBoundsToDomain(Domain, tempScop);
1016 Domain = addConditionsToDomain(Domain, tempScop, CurRegion);
Tobias Grosser084d8f72012-05-29 09:29:44 +00001017 Domain = isl_set_set_tuple_id(Domain, Id);
Tobias Grossere19661e2011-10-07 08:46:57 +00001018
1019 return Domain;
Tobias Grosser75805372011-04-29 06:27:02 +00001020}
1021
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001022void ScopStmt::deriveAssumptionsFromGEP(GetElementPtrInst *GEP) {
1023 int Dimension = 0;
1024 isl_ctx *Ctx = Parent.getIslCtx();
1025 isl_local_space *LSpace = isl_local_space_from_space(getDomainSpace());
1026 Type *Ty = GEP->getPointerOperandType();
1027 ScalarEvolution &SE = *Parent.getSE();
1028
1029 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
1030 Dimension = 1;
1031 Ty = PtrTy->getElementType();
1032 }
1033
1034 while (auto ArrayTy = dyn_cast<ArrayType>(Ty)) {
1035 unsigned int Operand = 1 + Dimension;
1036
1037 if (GEP->getNumOperands() <= Operand)
1038 break;
1039
1040 const SCEV *Expr = SE.getSCEV(GEP->getOperand(Operand));
1041
1042 if (isAffineExpr(&Parent.getRegion(), Expr, SE)) {
1043 isl_pw_aff *AccessOffset = SCEVAffinator::getPwAff(this, Expr);
1044 AccessOffset =
1045 isl_pw_aff_set_tuple_id(AccessOffset, isl_dim_in, getDomainId());
1046
1047 isl_pw_aff *DimSize = isl_pw_aff_from_aff(isl_aff_val_on_domain(
1048 isl_local_space_copy(LSpace),
1049 isl_val_int_from_si(Ctx, ArrayTy->getNumElements())));
1050
1051 isl_set *OutOfBound = isl_pw_aff_ge_set(AccessOffset, DimSize);
1052 OutOfBound = isl_set_intersect(getDomain(), OutOfBound);
1053 OutOfBound = isl_set_params(OutOfBound);
1054 isl_set *InBound = isl_set_complement(OutOfBound);
1055 isl_set *Executed = isl_set_params(getDomain());
1056
1057 // A => B == !A or B
1058 isl_set *InBoundIfExecuted =
1059 isl_set_union(isl_set_complement(Executed), InBound);
1060
1061 Parent.addAssumption(InBoundIfExecuted);
1062 }
1063
1064 Dimension += 1;
1065 Ty = ArrayTy->getElementType();
1066 }
1067
1068 isl_local_space_free(LSpace);
1069}
1070
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001071void ScopStmt::deriveAssumptions(BasicBlock *Block) {
1072 for (Instruction &Inst : *Block)
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001073 if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst))
1074 deriveAssumptionsFromGEP(GEP);
1075}
1076
Tobias Grosser74394f02013-01-14 22:40:23 +00001077ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001078 Region &R, SmallVectorImpl<Loop *> &Nest,
Tobias Grosser54839312015-04-21 11:37:25 +00001079 SmallVectorImpl<unsigned> &ScheduleVec)
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001080 : Parent(parent), BB(nullptr), R(&R), Build(nullptr),
1081 NestLoops(Nest.size()) {
1082 // Setup the induction variables.
1083 for (unsigned i = 0, e = Nest.size(); i < e; ++i)
1084 NestLoops[i] = Nest[i];
1085
1086 BaseName = getIslCompatibleName("Stmt_(", R.getNameStr(), ")");
1087
1088 Domain = buildDomain(tempScop, CurRegion);
Tobias Grosser54839312015-04-21 11:37:25 +00001089 buildSchedule(ScheduleVec);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001090
1091 BasicBlock *EntryBB = R.getEntry();
1092 for (BasicBlock *Block : R.blocks()) {
1093 buildAccesses(tempScop, Block, Block != EntryBB);
1094 deriveAssumptions(Block);
1095 }
1096 checkForReductions();
1097}
1098
1099ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
Sebastian Pop860e0212013-02-15 21:26:44 +00001100 BasicBlock &bb, SmallVectorImpl<Loop *> &Nest,
Tobias Grosser54839312015-04-21 11:37:25 +00001101 SmallVectorImpl<unsigned> &ScheduleVec)
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001102 : Parent(parent), BB(&bb), R(nullptr), Build(nullptr),
1103 NestLoops(Nest.size()) {
Tobias Grosser75805372011-04-29 06:27:02 +00001104 // Setup the induction variables.
Tobias Grosser683b8e42014-11-30 14:33:31 +00001105 for (unsigned i = 0, e = Nest.size(); i < e; ++i)
Sebastian Pop860e0212013-02-15 21:26:44 +00001106 NestLoops[i] = Nest[i];
Tobias Grosser75805372011-04-29 06:27:02 +00001107
Johannes Doerfert79fc23f2014-07-24 23:48:02 +00001108 BaseName = getIslCompatibleName("Stmt_", &bb, "");
Tobias Grosser75805372011-04-29 06:27:02 +00001109
Tobias Grossere19661e2011-10-07 08:46:57 +00001110 Domain = buildDomain(tempScop, CurRegion);
Tobias Grosser54839312015-04-21 11:37:25 +00001111 buildSchedule(ScheduleVec);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001112 buildAccesses(tempScop, BB);
1113 deriveAssumptions(BB);
Johannes Doerferte58a0122014-06-27 20:31:28 +00001114 checkForReductions();
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001115}
1116
Johannes Doerferte58a0122014-06-27 20:31:28 +00001117/// @brief Collect loads which might form a reduction chain with @p StoreMA
1118///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001119/// Check if the stored value for @p StoreMA is a binary operator with one or
1120/// two loads as operands. If the binary operand is commutative & associative,
Johannes Doerferte58a0122014-06-27 20:31:28 +00001121/// used only once (by @p StoreMA) and its load operands are also used only
1122/// once, we have found a possible reduction chain. It starts at an operand
1123/// load and includes the binary operator and @p StoreMA.
1124///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001125/// Note: We allow only one use to ensure the load and binary operator cannot
Johannes Doerferte58a0122014-06-27 20:31:28 +00001126/// escape this block or into any other store except @p StoreMA.
1127void ScopStmt::collectCandiateReductionLoads(
1128 MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) {
1129 auto *Store = dyn_cast<StoreInst>(StoreMA->getAccessInstruction());
1130 if (!Store)
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001131 return;
1132
1133 // Skip if there is not one binary operator between the load and the store
1134 auto *BinOp = dyn_cast<BinaryOperator>(Store->getValueOperand());
Johannes Doerferte58a0122014-06-27 20:31:28 +00001135 if (!BinOp)
1136 return;
1137
1138 // Skip if the binary operators has multiple uses
1139 if (BinOp->getNumUses() != 1)
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001140 return;
1141
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001142 // Skip if the opcode of the binary operator is not commutative/associative
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001143 if (!BinOp->isCommutative() || !BinOp->isAssociative())
1144 return;
1145
Johannes Doerfert9890a052014-07-01 00:32:29 +00001146 // Skip if the binary operator is outside the current SCoP
1147 if (BinOp->getParent() != Store->getParent())
1148 return;
1149
Johannes Doerfert0ee1f212014-06-17 17:31:36 +00001150 // Skip if it is a multiplicative reduction and we disabled them
1151 if (DisableMultiplicativeReductions &&
1152 (BinOp->getOpcode() == Instruction::Mul ||
1153 BinOp->getOpcode() == Instruction::FMul))
1154 return;
1155
Johannes Doerferte58a0122014-06-27 20:31:28 +00001156 // Check the binary operator operands for a candidate load
1157 auto *PossibleLoad0 = dyn_cast<LoadInst>(BinOp->getOperand(0));
1158 auto *PossibleLoad1 = dyn_cast<LoadInst>(BinOp->getOperand(1));
1159 if (!PossibleLoad0 && !PossibleLoad1)
1160 return;
1161
1162 // A load is only a candidate if it cannot escape (thus has only this use)
1163 if (PossibleLoad0 && PossibleLoad0->getNumUses() == 1)
Johannes Doerfert9890a052014-07-01 00:32:29 +00001164 if (PossibleLoad0->getParent() == Store->getParent())
1165 Loads.push_back(lookupAccessFor(PossibleLoad0));
Johannes Doerferte58a0122014-06-27 20:31:28 +00001166 if (PossibleLoad1 && PossibleLoad1->getNumUses() == 1)
Johannes Doerfert9890a052014-07-01 00:32:29 +00001167 if (PossibleLoad1->getParent() == Store->getParent())
1168 Loads.push_back(lookupAccessFor(PossibleLoad1));
Johannes Doerferte58a0122014-06-27 20:31:28 +00001169}
1170
1171/// @brief Check for reductions in this ScopStmt
1172///
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001173/// Iterate over all store memory accesses and check for valid binary reduction
1174/// like chains. For all candidates we check if they have the same base address
1175/// and there are no other accesses which overlap with them. The base address
1176/// check rules out impossible reductions candidates early. The overlap check,
1177/// together with the "only one user" check in collectCandiateReductionLoads,
Johannes Doerferte58a0122014-06-27 20:31:28 +00001178/// guarantees that none of the intermediate results will escape during
1179/// execution of the loop nest. We basically check here that no other memory
1180/// access can access the same memory as the potential reduction.
1181void ScopStmt::checkForReductions() {
1182 SmallVector<MemoryAccess *, 2> Loads;
1183 SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
1184
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001185 // First collect candidate load-store reduction chains by iterating over all
Johannes Doerferte58a0122014-06-27 20:31:28 +00001186 // stores and collecting possible reduction loads.
1187 for (MemoryAccess *StoreMA : MemAccs) {
1188 if (StoreMA->isRead())
1189 continue;
1190
1191 Loads.clear();
1192 collectCandiateReductionLoads(StoreMA, Loads);
1193 for (MemoryAccess *LoadMA : Loads)
1194 Candidates.push_back(std::make_pair(LoadMA, StoreMA));
1195 }
1196
1197 // Then check each possible candidate pair.
1198 for (const auto &CandidatePair : Candidates) {
1199 bool Valid = true;
1200 isl_map *LoadAccs = CandidatePair.first->getAccessRelation();
1201 isl_map *StoreAccs = CandidatePair.second->getAccessRelation();
1202
1203 // Skip those with obviously unequal base addresses.
1204 if (!isl_map_has_equal_space(LoadAccs, StoreAccs)) {
1205 isl_map_free(LoadAccs);
1206 isl_map_free(StoreAccs);
1207 continue;
1208 }
1209
1210 // And check if the remaining for overlap with other memory accesses.
1211 isl_map *AllAccsRel = isl_map_union(LoadAccs, StoreAccs);
1212 AllAccsRel = isl_map_intersect_domain(AllAccsRel, getDomain());
1213 isl_set *AllAccs = isl_map_range(AllAccsRel);
1214
1215 for (MemoryAccess *MA : MemAccs) {
1216 if (MA == CandidatePair.first || MA == CandidatePair.second)
1217 continue;
1218
1219 isl_map *AccRel =
1220 isl_map_intersect_domain(MA->getAccessRelation(), getDomain());
1221 isl_set *Accs = isl_map_range(AccRel);
1222
1223 if (isl_set_has_equal_space(AllAccs, Accs) || isl_set_free(Accs)) {
1224 isl_set *OverlapAccs = isl_set_intersect(Accs, isl_set_copy(AllAccs));
1225 Valid = Valid && isl_set_is_empty(OverlapAccs);
1226 isl_set_free(OverlapAccs);
1227 }
1228 }
1229
1230 isl_set_free(AllAccs);
1231 if (!Valid)
1232 continue;
1233
Johannes Doerfertf6183392014-07-01 20:52:51 +00001234 const LoadInst *Load =
1235 dyn_cast<const LoadInst>(CandidatePair.first->getAccessInstruction());
1236 MemoryAccess::ReductionType RT =
1237 getReductionType(dyn_cast<BinaryOperator>(Load->user_back()), Load);
1238
Johannes Doerferte58a0122014-06-27 20:31:28 +00001239 // If no overlapping access was found we mark the load and store as
1240 // reduction like.
Johannes Doerfertf6183392014-07-01 20:52:51 +00001241 CandidatePair.first->markAsReductionLike(RT);
1242 CandidatePair.second->markAsReductionLike(RT);
Johannes Doerferte58a0122014-06-27 20:31:28 +00001243 }
Tobias Grosser75805372011-04-29 06:27:02 +00001244}
1245
Tobias Grosser74394f02013-01-14 22:40:23 +00001246std::string ScopStmt::getDomainStr() const { return stringFromIslObj(Domain); }
Tobias Grosser75805372011-04-29 06:27:02 +00001247
Tobias Grosser54839312015-04-21 11:37:25 +00001248std::string ScopStmt::getScheduleStr() const {
1249 return stringFromIslObj(Schedule);
Tobias Grosser75805372011-04-29 06:27:02 +00001250}
1251
Tobias Grosser74394f02013-01-14 22:40:23 +00001252unsigned ScopStmt::getNumParams() const { return Parent.getNumParams(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001253
Tobias Grosserf567e1a2015-02-19 22:16:12 +00001254unsigned ScopStmt::getNumIterators() const { return NestLoops.size(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001255
Tobias Grosser54839312015-04-21 11:37:25 +00001256unsigned ScopStmt::getNumSchedule() const {
1257 return isl_map_dim(Schedule, isl_dim_out);
Tobias Grosser75805372011-04-29 06:27:02 +00001258}
1259
1260const char *ScopStmt::getBaseName() const { return BaseName.c_str(); }
1261
Hongbin Zheng27f3afb2011-04-30 03:26:51 +00001262const Loop *ScopStmt::getLoopForDimension(unsigned Dimension) const {
Sebastian Pop860e0212013-02-15 21:26:44 +00001263 return NestLoops[Dimension];
Tobias Grosser75805372011-04-29 06:27:02 +00001264}
1265
Tobias Grosser74394f02013-01-14 22:40:23 +00001266isl_ctx *ScopStmt::getIslCtx() const { return Parent.getIslCtx(); }
Tobias Grosser75805372011-04-29 06:27:02 +00001267
Tobias Grosser4f663aa2015-03-30 11:52:59 +00001268__isl_give isl_set *ScopStmt::getDomain() const { return isl_set_copy(Domain); }
Tobias Grosserd5a7bfc2011-05-06 19:52:19 +00001269
Tobias Grosser6e6c7e02015-03-30 12:22:39 +00001270__isl_give isl_space *ScopStmt::getDomainSpace() const {
Tobias Grosser78d8a3d2012-01-17 20:34:23 +00001271 return isl_set_get_space(Domain);
1272}
1273
Tobias Grosser4f663aa2015-03-30 11:52:59 +00001274__isl_give isl_id *ScopStmt::getDomainId() const {
1275 return isl_set_get_tuple_id(Domain);
1276}
Tobias Grossercd95b772012-08-30 11:49:38 +00001277
Tobias Grosser75805372011-04-29 06:27:02 +00001278ScopStmt::~ScopStmt() {
Johannes Doerfertecff11d2015-05-22 23:43:58 +00001279 DeleteContainerSeconds(InstructionToAccess);
Tobias Grosser75805372011-04-29 06:27:02 +00001280 isl_set_free(Domain);
Tobias Grosser54839312015-04-21 11:37:25 +00001281 isl_map_free(Schedule);
Tobias Grosser75805372011-04-29 06:27:02 +00001282}
1283
1284void ScopStmt::print(raw_ostream &OS) const {
1285 OS << "\t" << getBaseName() << "\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001286 OS.indent(12) << "Domain :=\n";
1287
1288 if (Domain) {
1289 OS.indent(16) << getDomainStr() << ";\n";
1290 } else
1291 OS.indent(16) << "n/a\n";
1292
Tobias Grosser54839312015-04-21 11:37:25 +00001293 OS.indent(12) << "Schedule :=\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001294
1295 if (Domain) {
Tobias Grosser54839312015-04-21 11:37:25 +00001296 OS.indent(16) << getScheduleStr() << ";\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001297 } else
1298 OS.indent(16) << "n/a\n";
1299
Tobias Grosser083d3d32014-06-28 08:59:45 +00001300 for (MemoryAccess *Access : MemAccs)
1301 Access->print(OS);
Tobias Grosser75805372011-04-29 06:27:02 +00001302}
1303
1304void ScopStmt::dump() const { print(dbgs()); }
1305
1306//===----------------------------------------------------------------------===//
1307/// Scop class implement
Tobias Grosser60b54f12011-11-08 15:41:28 +00001308
Tobias Grosser7ffe4e82011-11-17 12:56:10 +00001309void Scop::setContext(__isl_take isl_set *NewContext) {
Tobias Grosserff9b54d2011-11-15 11:38:44 +00001310 NewContext = isl_set_align_params(NewContext, isl_set_get_space(Context));
1311 isl_set_free(Context);
1312 Context = NewContext;
1313}
1314
Tobias Grosserabfbe632013-02-05 12:09:06 +00001315void Scop::addParams(std::vector<const SCEV *> NewParameters) {
Tobias Grosser083d3d32014-06-28 08:59:45 +00001316 for (const SCEV *Parameter : NewParameters) {
Johannes Doerfertbe409962015-03-29 20:45:09 +00001317 Parameter = extractConstantFactor(Parameter, *SE).second;
Tobias Grosser60b54f12011-11-08 15:41:28 +00001318 if (ParameterIds.find(Parameter) != ParameterIds.end())
1319 continue;
1320
1321 int dimension = Parameters.size();
1322
1323 Parameters.push_back(Parameter);
1324 ParameterIds[Parameter] = dimension;
1325 }
1326}
1327
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001328__isl_give isl_id *Scop::getIdForParam(const SCEV *Parameter) const {
1329 ParamIdType::const_iterator IdIter = ParameterIds.find(Parameter);
Tobias Grosser76c2e322011-11-07 12:58:59 +00001330
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001331 if (IdIter == ParameterIds.end())
Tobias Grosser5a56cbf2014-04-16 07:33:47 +00001332 return nullptr;
Tobias Grosser76c2e322011-11-07 12:58:59 +00001333
Tobias Grosser8f99c162011-11-15 11:38:55 +00001334 std::string ParameterName;
1335
1336 if (const SCEVUnknown *ValueParameter = dyn_cast<SCEVUnknown>(Parameter)) {
1337 Value *Val = ValueParameter->getValue();
Tobias Grosser29ee0b12011-11-17 14:52:36 +00001338 ParameterName = Val->getName();
Tobias Grosser8f99c162011-11-15 11:38:55 +00001339 }
1340
1341 if (ParameterName == "" || ParameterName.substr(0, 2) == "p_")
Hongbin Zheng86a37742012-04-25 08:01:38 +00001342 ParameterName = "p_" + utostr_32(IdIter->second);
Tobias Grosser8f99c162011-11-15 11:38:55 +00001343
Tobias Grosser20532b82014-04-11 17:56:49 +00001344 return isl_id_alloc(getIslCtx(), ParameterName.c_str(),
1345 const_cast<void *>((const void *)Parameter));
Tobias Grosser76c2e322011-11-07 12:58:59 +00001346}
Tobias Grosser75805372011-04-29 06:27:02 +00001347
Tobias Grosser6be480c2011-11-08 15:41:13 +00001348void Scop::buildContext() {
1349 isl_space *Space = isl_space_params_alloc(IslCtx, 0);
Tobias Grossere86109f2013-10-29 21:05:49 +00001350 Context = isl_set_universe(isl_space_copy(Space));
1351 AssumedContext = isl_set_universe(Space);
Tobias Grosser0e27e242011-10-06 00:03:48 +00001352}
1353
Tobias Grosser18daaca2012-05-22 10:47:27 +00001354void Scop::addParameterBounds() {
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001355 for (const auto &ParamID : ParameterIds) {
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001356 int dim = ParamID.second;
Tobias Grosser18daaca2012-05-22 10:47:27 +00001357
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001358 ConstantRange SRange = SE->getSignedRange(ParamID.first);
Tobias Grosser18daaca2012-05-22 10:47:27 +00001359
Johannes Doerferte7044942015-02-24 11:58:30 +00001360 Context = addRangeBoundsToSet(Context, SRange, dim, isl_dim_param);
Tobias Grosser18daaca2012-05-22 10:47:27 +00001361 }
1362}
1363
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001364void Scop::realignParams() {
Tobias Grosser6be480c2011-11-08 15:41:13 +00001365 // Add all parameters into a common model.
Tobias Grosser60b54f12011-11-08 15:41:28 +00001366 isl_space *Space = isl_space_params_alloc(IslCtx, ParameterIds.size());
Tobias Grosser6be480c2011-11-08 15:41:13 +00001367
Tobias Grosser083d3d32014-06-28 08:59:45 +00001368 for (const auto &ParamID : ParameterIds) {
1369 const SCEV *Parameter = ParamID.first;
Tobias Grosser6be480c2011-11-08 15:41:13 +00001370 isl_id *id = getIdForParam(Parameter);
Tobias Grosser083d3d32014-06-28 08:59:45 +00001371 Space = isl_space_set_dim_id(Space, isl_dim_param, ParamID.second, id);
Tobias Grosser6be480c2011-11-08 15:41:13 +00001372 }
1373
1374 // Align the parameters of all data structures to the model.
1375 Context = isl_set_align_params(Context, Space);
1376
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001377 for (ScopStmt &Stmt : *this)
1378 Stmt.realignParams();
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001379}
1380
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001381void Scop::simplifyAssumedContext() {
1382 // The parameter constraints of the iteration domains give us a set of
1383 // constraints that need to hold for all cases where at least a single
1384 // statement iteration is executed in the whole scop. We now simplify the
1385 // assumed context under the assumption that such constraints hold and at
1386 // least a single statement iteration is executed. For cases where no
1387 // statement instances are executed, the assumptions we have taken about
1388 // the executed code do not matter and can be changed.
1389 //
1390 // WARNING: This only holds if the assumptions we have taken do not reduce
1391 // the set of statement instances that are executed. Otherwise we
1392 // may run into a case where the iteration domains suggest that
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001393 // for a certain set of parameter constraints no code is executed,
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001394 // but in the original program some computation would have been
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001395 // performed. In such a case, modifying the run-time conditions and
1396 // possibly influencing the run-time check may cause certain scops
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001397 // to not be executed.
1398 //
1399 // Example:
1400 //
1401 // When delinearizing the following code:
1402 //
1403 // for (long i = 0; i < 100; i++)
1404 // for (long j = 0; j < m; j++)
1405 // A[i+p][j] = 1.0;
1406 //
1407 // we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001408 // otherwise we would access out of bound data. Now, knowing that code is
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001409 // only executed for the case m >= 0, it is sufficient to assume p >= 0.
1410 AssumedContext =
1411 isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
Johannes Doerfert4f8ac3d2015-02-23 16:15:51 +00001412 AssumedContext = isl_set_gist_params(AssumedContext, getContext());
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001413}
1414
Johannes Doerfertb164c792014-09-18 11:17:17 +00001415/// @brief Add the minimal/maximal access in @p Set to @p User.
Tobias Grosserb2f39922015-05-28 13:32:11 +00001416static isl_stat buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00001417 Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User;
1418 isl_pw_multi_aff *MinPMA, *MaxPMA;
1419 isl_pw_aff *LastDimAff;
1420 isl_aff *OneAff;
1421 unsigned Pos;
1422
Johannes Doerfert9143d672014-09-27 11:02:39 +00001423 // Restrict the number of parameters involved in the access as the lexmin/
1424 // lexmax computation will take too long if this number is high.
1425 //
1426 // Experiments with a simple test case using an i7 4800MQ:
1427 //
1428 // #Parameters involved | Time (in sec)
1429 // 6 | 0.01
1430 // 7 | 0.04
1431 // 8 | 0.12
1432 // 9 | 0.40
1433 // 10 | 1.54
1434 // 11 | 6.78
1435 // 12 | 30.38
1436 //
1437 if (isl_set_n_param(Set) > RunTimeChecksMaxParameters) {
1438 unsigned InvolvedParams = 0;
1439 for (unsigned u = 0, e = isl_set_n_param(Set); u < e; u++)
1440 if (isl_set_involves_dims(Set, isl_dim_param, u, 1))
1441 InvolvedParams++;
1442
1443 if (InvolvedParams > RunTimeChecksMaxParameters) {
1444 isl_set_free(Set);
Tobias Grosserb2f39922015-05-28 13:32:11 +00001445 return isl_stat_error;
Johannes Doerfert9143d672014-09-27 11:02:39 +00001446 }
1447 }
1448
Johannes Doerfertb6755bb2015-02-14 12:00:06 +00001449 Set = isl_set_remove_divs(Set);
1450
Johannes Doerfertb164c792014-09-18 11:17:17 +00001451 MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set));
1452 MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set));
1453
Johannes Doerfert219b20e2014-10-07 14:37:59 +00001454 MinPMA = isl_pw_multi_aff_coalesce(MinPMA);
1455 MaxPMA = isl_pw_multi_aff_coalesce(MaxPMA);
1456
Johannes Doerfertb164c792014-09-18 11:17:17 +00001457 // Adjust the last dimension of the maximal access by one as we want to
1458 // enclose the accessed memory region by MinPMA and MaxPMA. The pointer
1459 // we test during code generation might now point after the end of the
1460 // allocated array but we will never dereference it anyway.
1461 assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) &&
1462 "Assumed at least one output dimension");
1463 Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1;
1464 LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos);
1465 OneAff = isl_aff_zero_on_domain(
1466 isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff)));
1467 OneAff = isl_aff_add_constant_si(OneAff, 1);
1468 LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff));
1469 MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff);
1470
1471 MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA));
1472
1473 isl_set_free(Set);
Tobias Grosserb2f39922015-05-28 13:32:11 +00001474 return isl_stat_ok;
Johannes Doerfertb164c792014-09-18 11:17:17 +00001475}
1476
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001477static __isl_give isl_set *getAccessDomain(MemoryAccess *MA) {
1478 isl_set *Domain = MA->getStatement()->getDomain();
1479 Domain = isl_set_project_out(Domain, isl_dim_set, 0, isl_set_n_dim(Domain));
1480 return isl_set_reset_tuple_id(Domain);
1481}
1482
Johannes Doerfert9143d672014-09-27 11:02:39 +00001483bool Scop::buildAliasGroups(AliasAnalysis &AA) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00001484 // To create sound alias checks we perform the following steps:
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001485 // o) Use the alias analysis and an alias set tracker to build alias sets
Johannes Doerfertb164c792014-09-18 11:17:17 +00001486 // for all memory accesses inside the SCoP.
1487 // o) For each alias set we then map the aliasing pointers back to the
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001488 // memory accesses we know, thus obtain groups of memory accesses which
Johannes Doerfertb164c792014-09-18 11:17:17 +00001489 // might alias.
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001490 // o) We divide each group based on the domains of the minimal/maximal
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001491 // accesses. That means two minimal/maximal accesses are only in a group
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001492 // if their access domains intersect, otherwise they are in different
1493 // ones.
Johannes Doerfert13771732014-10-01 12:40:46 +00001494 // o) We split groups such that they contain at most one read only base
1495 // address.
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001496 // o) For each group with more than one base pointer we then compute minimal
Johannes Doerfertb164c792014-09-18 11:17:17 +00001497 // and maximal accesses to each array in this group.
1498 using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
1499
1500 AliasSetTracker AST(AA);
1501
1502 DenseMap<Value *, MemoryAccess *> PtrToAcc;
Johannes Doerfert13771732014-10-01 12:40:46 +00001503 DenseSet<Value *> HasWriteAccess;
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001504 for (ScopStmt &Stmt : *this) {
Johannes Doerfertf1ee2622014-10-06 17:43:00 +00001505
1506 // Skip statements with an empty domain as they will never be executed.
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001507 isl_set *StmtDomain = Stmt.getDomain();
Johannes Doerfertf1ee2622014-10-06 17:43:00 +00001508 bool StmtDomainEmpty = isl_set_is_empty(StmtDomain);
1509 isl_set_free(StmtDomain);
1510 if (StmtDomainEmpty)
1511 continue;
1512
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001513 for (MemoryAccess *MA : Stmt) {
Johannes Doerfertb164c792014-09-18 11:17:17 +00001514 if (MA->isScalar())
1515 continue;
Johannes Doerfert13771732014-10-01 12:40:46 +00001516 if (!MA->isRead())
1517 HasWriteAccess.insert(MA->getBaseAddr());
Johannes Doerfertb164c792014-09-18 11:17:17 +00001518 Instruction *Acc = MA->getAccessInstruction();
1519 PtrToAcc[getPointerOperand(*Acc)] = MA;
1520 AST.add(Acc);
1521 }
1522 }
1523
1524 SmallVector<AliasGroupTy, 4> AliasGroups;
1525 for (AliasSet &AS : AST) {
Johannes Doerfert74f68692014-10-08 02:23:48 +00001526 if (AS.isMustAlias() || AS.isForwardingAliasSet())
Johannes Doerfertb164c792014-09-18 11:17:17 +00001527 continue;
1528 AliasGroupTy AG;
1529 for (auto PR : AS)
1530 AG.push_back(PtrToAcc[PR.getValue()]);
1531 assert(AG.size() > 1 &&
1532 "Alias groups should contain at least two accesses");
1533 AliasGroups.push_back(std::move(AG));
1534 }
1535
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001536 // Split the alias groups based on their domain.
1537 for (unsigned u = 0; u < AliasGroups.size(); u++) {
1538 AliasGroupTy NewAG;
1539 AliasGroupTy &AG = AliasGroups[u];
1540 AliasGroupTy::iterator AGI = AG.begin();
1541 isl_set *AGDomain = getAccessDomain(*AGI);
1542 while (AGI != AG.end()) {
1543 MemoryAccess *MA = *AGI;
1544 isl_set *MADomain = getAccessDomain(MA);
1545 if (isl_set_is_disjoint(AGDomain, MADomain)) {
1546 NewAG.push_back(MA);
1547 AGI = AG.erase(AGI);
1548 isl_set_free(MADomain);
1549 } else {
1550 AGDomain = isl_set_union(AGDomain, MADomain);
1551 AGI++;
1552 }
1553 }
1554 if (NewAG.size() > 1)
1555 AliasGroups.push_back(std::move(NewAG));
1556 isl_set_free(AGDomain);
1557 }
1558
Tobias Grosserf4c24b22015-04-05 13:11:54 +00001559 MapVector<const Value *, SmallPtrSet<MemoryAccess *, 8>> ReadOnlyPairs;
Johannes Doerfert13771732014-10-01 12:40:46 +00001560 SmallPtrSet<const Value *, 4> NonReadOnlyBaseValues;
1561 for (AliasGroupTy &AG : AliasGroups) {
1562 NonReadOnlyBaseValues.clear();
1563 ReadOnlyPairs.clear();
1564
Johannes Doerferteeab05a2014-10-01 12:42:37 +00001565 if (AG.size() < 2) {
1566 AG.clear();
1567 continue;
1568 }
1569
Johannes Doerfert13771732014-10-01 12:40:46 +00001570 for (auto II = AG.begin(); II != AG.end();) {
1571 Value *BaseAddr = (*II)->getBaseAddr();
1572 if (HasWriteAccess.count(BaseAddr)) {
1573 NonReadOnlyBaseValues.insert(BaseAddr);
1574 II++;
1575 } else {
1576 ReadOnlyPairs[BaseAddr].insert(*II);
1577 II = AG.erase(II);
1578 }
1579 }
1580
1581 // If we don't have read only pointers check if there are at least two
1582 // non read only pointers, otherwise clear the alias group.
1583 if (ReadOnlyPairs.empty()) {
1584 if (NonReadOnlyBaseValues.size() <= 1)
1585 AG.clear();
1586 continue;
1587 }
1588
1589 // If we don't have non read only pointers clear the alias group.
1590 if (NonReadOnlyBaseValues.empty()) {
1591 AG.clear();
1592 continue;
1593 }
1594
1595 // If we have both read only and non read only base pointers we combine
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00001596 // the non read only ones with exactly one read only one at a time into a
Johannes Doerfert13771732014-10-01 12:40:46 +00001597 // new alias group and clear the old alias group in the end.
1598 for (const auto &ReadOnlyPair : ReadOnlyPairs) {
1599 AliasGroupTy AGNonReadOnly = AG;
1600 for (MemoryAccess *MA : ReadOnlyPair.second)
1601 AGNonReadOnly.push_back(MA);
1602 AliasGroups.push_back(std::move(AGNonReadOnly));
1603 }
1604 AG.clear();
Johannes Doerfertb164c792014-09-18 11:17:17 +00001605 }
1606
1607 for (AliasGroupTy &AG : AliasGroups) {
Johannes Doerfert13771732014-10-01 12:40:46 +00001608 if (AG.empty())
1609 continue;
1610
Johannes Doerfertb164c792014-09-18 11:17:17 +00001611 MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
1612 MinMaxAccesses->reserve(AG.size());
1613
1614 isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
1615 for (MemoryAccess *MA : AG)
1616 Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
1617 Accesses = isl_union_map_intersect_domain(Accesses, getDomains());
1618
1619 isl_union_set *Locations = isl_union_map_range(Accesses);
1620 Locations = isl_union_set_intersect_params(Locations, getAssumedContext());
1621 Locations = isl_union_set_coalesce(Locations);
1622 Locations = isl_union_set_detect_equalities(Locations);
Tobias Grosser50d4e2e2015-03-28 14:50:32 +00001623 bool Valid = (0 == isl_union_set_foreach_set(Locations, buildMinMaxAccess,
1624 MinMaxAccesses));
Johannes Doerfertb164c792014-09-18 11:17:17 +00001625 isl_union_set_free(Locations);
Johannes Doerfertb164c792014-09-18 11:17:17 +00001626 MinMaxAliasGroups.push_back(MinMaxAccesses);
Johannes Doerfert9143d672014-09-27 11:02:39 +00001627
1628 if (!Valid)
Tobias Grosser50d4e2e2015-03-28 14:50:32 +00001629 return false;
Johannes Doerfertb164c792014-09-18 11:17:17 +00001630 }
Johannes Doerfert9143d672014-09-27 11:02:39 +00001631
Tobias Grosser71500722015-03-28 15:11:14 +00001632 // Bail out if the number of values we need to compare is too large.
1633 // This is important as the number of comparisions grows quadratically with
1634 // the number of values we need to compare.
1635 for (const auto *Values : MinMaxAliasGroups)
1636 if (Values->size() > RunTimeChecksMaxArraysPerGroup)
1637 return false;
1638
Tobias Grosser50d4e2e2015-03-28 14:50:32 +00001639 return true;
Johannes Doerfertb164c792014-09-18 11:17:17 +00001640}
1641
Johannes Doerfertf8206cf2015-04-12 22:58:40 +00001642static unsigned getMaxLoopDepthInRegion(const Region &R, LoopInfo &LI,
1643 ScopDetection &SD) {
1644
1645 const ScopDetection::BoxedLoopsSetTy *BoxedLoops = SD.getBoxedLoops(&R);
1646
Johannes Doerferte3da05a2014-11-01 00:12:13 +00001647 unsigned MinLD = INT_MAX, MaxLD = 0;
1648 for (BasicBlock *BB : R.blocks()) {
1649 if (Loop *L = LI.getLoopFor(BB)) {
David Peixottodc0a11c2015-01-13 18:31:55 +00001650 if (!R.contains(L))
1651 continue;
Johannes Doerfertf8206cf2015-04-12 22:58:40 +00001652 if (BoxedLoops && BoxedLoops->count(L))
1653 continue;
Johannes Doerferte3da05a2014-11-01 00:12:13 +00001654 unsigned LD = L->getLoopDepth();
1655 MinLD = std::min(MinLD, LD);
1656 MaxLD = std::max(MaxLD, LD);
1657 }
1658 }
1659
1660 // Handle the case that there is no loop in the SCoP first.
1661 if (MaxLD == 0)
1662 return 1;
1663
1664 assert(MinLD >= 1 && "Minimal loop depth should be at least one");
1665 assert(MaxLD >= MinLD &&
1666 "Maximal loop depth was smaller than mininaml loop depth?");
1667 return MaxLD - MinLD + 1;
1668}
1669
Tobias Grosser3f296192015-01-01 23:01:11 +00001670void Scop::dropConstantScheduleDims() {
1671 isl_union_map *FullSchedule = getSchedule();
1672
1673 if (isl_union_map_n_map(FullSchedule) == 0) {
1674 isl_union_map_free(FullSchedule);
1675 return;
1676 }
1677
1678 isl_set *ScheduleSpace =
1679 isl_set_from_union_set(isl_union_map_range(FullSchedule));
1680 isl_map *DropDimMap = isl_set_identity(isl_set_copy(ScheduleSpace));
1681
1682 int NumDimsDropped = 0;
Johannes Doerfert3f21e272015-03-04 22:23:21 +00001683 for (unsigned i = 0; i < isl_set_dim(ScheduleSpace, isl_dim_set); i += 2) {
1684 isl_val *FixedVal =
1685 isl_set_plain_get_val_if_fixed(ScheduleSpace, isl_dim_set, i);
1686 if (isl_val_is_int(FixedVal)) {
1687 DropDimMap =
1688 isl_map_project_out(DropDimMap, isl_dim_out, i - NumDimsDropped, 1);
1689 NumDimsDropped++;
Tobias Grosser3f296192015-01-01 23:01:11 +00001690 }
Johannes Doerfert3f21e272015-03-04 22:23:21 +00001691 isl_val_free(FixedVal);
1692 }
Tobias Grosser3f296192015-01-01 23:01:11 +00001693
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001694 for (ScopStmt &Stmt : *this) {
1695 isl_map *Schedule = Stmt.getSchedule();
Tobias Grosser3f296192015-01-01 23:01:11 +00001696 Schedule = isl_map_apply_range(Schedule, isl_map_copy(DropDimMap));
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001697 Stmt.setSchedule(Schedule);
Tobias Grosser3f296192015-01-01 23:01:11 +00001698 }
1699 isl_set_free(ScheduleSpace);
1700 isl_map_free(DropDimMap);
1701}
1702
Tobias Grosser0e27e242011-10-06 00:03:48 +00001703Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001704 ScopDetection &SD, isl_ctx *Context)
Johannes Doerfert7ceb0402015-02-11 17:25:09 +00001705 : SE(&ScalarEvolution), R(tempScop.getMaxRegion()), IsOptimized(false),
Johannes Doerfertf8206cf2015-04-12 22:58:40 +00001706 MaxLoopDepth(getMaxLoopDepthInRegion(tempScop.getMaxRegion(), LI, SD)) {
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001707 IslCtx = Context;
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001708
Tobias Grosser6be480c2011-11-08 15:41:13 +00001709 buildContext();
Tobias Grosser75805372011-04-29 06:27:02 +00001710
Tobias Grosserabfbe632013-02-05 12:09:06 +00001711 SmallVector<Loop *, 8> NestLoops;
Tobias Grosser54839312015-04-21 11:37:25 +00001712 SmallVector<unsigned, 8> Schedule;
Tobias Grosser75805372011-04-29 06:27:02 +00001713
Tobias Grosser54839312015-04-21 11:37:25 +00001714 Schedule.assign(MaxLoopDepth + 1, 0);
Tobias Grosser75805372011-04-29 06:27:02 +00001715
Tobias Grosser54839312015-04-21 11:37:25 +00001716 // Build the iteration domain, access functions and schedule functions
Tobias Grosser75805372011-04-29 06:27:02 +00001717 // traversing the region tree.
Tobias Grosser54839312015-04-21 11:37:25 +00001718 buildScop(tempScop, getRegion(), NestLoops, Schedule, LI, SD);
Tobias Grosser75805372011-04-29 06:27:02 +00001719
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001720 realignParams();
Tobias Grosser18daaca2012-05-22 10:47:27 +00001721 addParameterBounds();
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001722 simplifyAssumedContext();
Tobias Grosser3f296192015-01-01 23:01:11 +00001723 dropConstantScheduleDims();
Tobias Grosser8cae72f2011-11-08 15:41:08 +00001724
Tobias Grosser75805372011-04-29 06:27:02 +00001725 assert(NestLoops.empty() && "NestLoops not empty at top level!");
1726}
1727
1728Scop::~Scop() {
1729 isl_set_free(Context);
Tobias Grossere86109f2013-10-29 21:05:49 +00001730 isl_set_free(AssumedContext);
Tobias Grosser75805372011-04-29 06:27:02 +00001731
Johannes Doerfertb164c792014-09-18 11:17:17 +00001732 // Free the alias groups
1733 for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
1734 for (MinMaxAccessTy &MMA : *MinMaxAccesses) {
1735 isl_pw_multi_aff_free(MMA.first);
1736 isl_pw_multi_aff_free(MMA.second);
1737 }
1738 delete MinMaxAccesses;
1739 }
Tobias Grosser75805372011-04-29 06:27:02 +00001740}
1741
Johannes Doerfert80ef1102014-11-07 08:31:31 +00001742const ScopArrayInfo *
1743Scop::getOrCreateScopArrayInfo(Value *BasePtr, Type *AccessType,
1744 const SmallVector<const SCEV *, 4> &Sizes) {
Tobias Grosserab671442015-05-23 05:58:27 +00001745 auto &SAI = ScopArrayInfoMap[BasePtr];
Johannes Doerfert80ef1102014-11-07 08:31:31 +00001746 if (!SAI)
Tobias Grosserab671442015-05-23 05:58:27 +00001747 SAI.reset(new ScopArrayInfo(BasePtr, AccessType, getIslCtx(), Sizes));
1748 return SAI.get();
Johannes Doerfert1a28a892014-10-05 11:32:18 +00001749}
1750
1751const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr) {
Tobias Grosser2d7611f2015-05-23 05:58:30 +00001752 const ScopArrayInfo *SAI = ScopArrayInfoMap[BasePtr].get();
Johannes Doerfert1a28a892014-10-05 11:32:18 +00001753 assert(SAI && "No ScopArrayInfo available for this base pointer");
1754 return SAI;
1755}
1756
Tobias Grosser74394f02013-01-14 22:40:23 +00001757std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001758std::string Scop::getAssumedContextStr() const {
1759 return stringFromIslObj(AssumedContext);
1760}
Tobias Grosser75805372011-04-29 06:27:02 +00001761
1762std::string Scop::getNameStr() const {
1763 std::string ExitName, EntryName;
1764 raw_string_ostream ExitStr(ExitName);
1765 raw_string_ostream EntryStr(EntryName);
1766
Tobias Grosserf240b482014-01-09 10:42:15 +00001767 R.getEntry()->printAsOperand(EntryStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00001768 EntryStr.str();
1769
1770 if (R.getExit()) {
Tobias Grosserf240b482014-01-09 10:42:15 +00001771 R.getExit()->printAsOperand(ExitStr, false);
Tobias Grosser75805372011-04-29 06:27:02 +00001772 ExitStr.str();
1773 } else
1774 ExitName = "FunctionExit";
1775
1776 return EntryName + "---" + ExitName;
1777}
1778
Tobias Grosser74394f02013-01-14 22:40:23 +00001779__isl_give isl_set *Scop::getContext() const { return isl_set_copy(Context); }
Tobias Grosser37487052011-10-06 00:03:42 +00001780__isl_give isl_space *Scop::getParamSpace() const {
Tobias Grossereeb9f3c2015-05-26 21:37:31 +00001781 return isl_set_get_space(Context);
Tobias Grosser37487052011-10-06 00:03:42 +00001782}
1783
Tobias Grossere86109f2013-10-29 21:05:49 +00001784__isl_give isl_set *Scop::getAssumedContext() const {
1785 return isl_set_copy(AssumedContext);
1786}
1787
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001788void Scop::addAssumption(__isl_take isl_set *Set) {
1789 AssumedContext = isl_set_intersect(AssumedContext, Set);
Tobias Grosser7b50bee2014-11-25 10:51:12 +00001790 AssumedContext = isl_set_coalesce(AssumedContext);
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001791}
1792
Tobias Grosser75805372011-04-29 06:27:02 +00001793void Scop::printContext(raw_ostream &OS) const {
1794 OS << "Context:\n";
1795
1796 if (!Context) {
1797 OS.indent(4) << "n/a\n\n";
1798 return;
1799 }
1800
1801 OS.indent(4) << getContextStr() << "\n";
Tobias Grosser60b54f12011-11-08 15:41:28 +00001802
Tobias Grosser5e6813d2014-07-02 17:47:48 +00001803 OS.indent(4) << "Assumed Context:\n";
1804 if (!AssumedContext) {
1805 OS.indent(4) << "n/a\n\n";
1806 return;
1807 }
1808
1809 OS.indent(4) << getAssumedContextStr() << "\n";
1810
Tobias Grosser083d3d32014-06-28 08:59:45 +00001811 for (const SCEV *Parameter : Parameters) {
Tobias Grosser60b54f12011-11-08 15:41:28 +00001812 int Dim = ParameterIds.find(Parameter)->second;
Tobias Grosser60b54f12011-11-08 15:41:28 +00001813 OS.indent(4) << "p" << Dim << ": " << *Parameter << "\n";
1814 }
Tobias Grosser75805372011-04-29 06:27:02 +00001815}
1816
Johannes Doerfertb164c792014-09-18 11:17:17 +00001817void Scop::printAliasAssumptions(raw_ostream &OS) const {
1818 OS.indent(4) << "Alias Groups (" << MinMaxAliasGroups.size() << "):\n";
1819 if (MinMaxAliasGroups.empty()) {
1820 OS.indent(8) << "n/a\n";
1821 return;
1822 }
1823 for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
1824 OS.indent(8) << "[[";
1825 for (MinMaxAccessTy &MinMacAccess : *MinMaxAccesses)
1826 OS << " <" << MinMacAccess.first << ", " << MinMacAccess.second << ">";
1827 OS << " ]]\n";
1828 }
1829}
1830
Tobias Grosser75805372011-04-29 06:27:02 +00001831void Scop::printStatements(raw_ostream &OS) const {
1832 OS << "Statements {\n";
1833
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001834 for (const ScopStmt &Stmt : *this)
1835 OS.indent(4) << Stmt;
Tobias Grosser75805372011-04-29 06:27:02 +00001836
1837 OS.indent(4) << "}\n";
1838}
1839
Tobias Grosser49ad36c2015-05-20 08:05:31 +00001840void Scop::printArrayInfo(raw_ostream &OS) const {
1841 OS << "Arrays {\n";
1842
Tobias Grosserab671442015-05-23 05:58:27 +00001843 for (auto &Array : arrays())
Tobias Grosser49ad36c2015-05-20 08:05:31 +00001844 Array.second->print(OS);
1845
1846 OS.indent(4) << "}\n";
1847}
1848
Tobias Grosser75805372011-04-29 06:27:02 +00001849void Scop::print(raw_ostream &OS) const {
Tobias Grosser4eb7ddb2014-03-18 18:51:11 +00001850 OS.indent(4) << "Function: " << getRegion().getEntry()->getParent()->getName()
1851 << "\n";
Tobias Grosser483fdd42014-03-18 18:05:38 +00001852 OS.indent(4) << "Region: " << getNameStr() << "\n";
David Peixottodc0a11c2015-01-13 18:31:55 +00001853 OS.indent(4) << "Max Loop Depth: " << getMaxLoopDepth() << "\n";
Tobias Grosser75805372011-04-29 06:27:02 +00001854 printContext(OS.indent(4));
Tobias Grosser49ad36c2015-05-20 08:05:31 +00001855 printArrayInfo(OS.indent(4));
Johannes Doerfertb164c792014-09-18 11:17:17 +00001856 printAliasAssumptions(OS);
Tobias Grosser75805372011-04-29 06:27:02 +00001857 printStatements(OS.indent(4));
1858}
1859
1860void Scop::dump() const { print(dbgs()); }
1861
Tobias Grosser9a38ab82011-11-08 15:41:03 +00001862isl_ctx *Scop::getIslCtx() const { return IslCtx; }
Tobias Grosser75805372011-04-29 06:27:02 +00001863
Tobias Grosser5f9a7622012-02-14 14:02:40 +00001864__isl_give isl_union_set *Scop::getDomains() {
Tobias Grosserbc4ef902014-06-28 08:59:38 +00001865 isl_union_set *Domain = isl_union_set_empty(getParamSpace());
Tobias Grosser5f9a7622012-02-14 14:02:40 +00001866
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001867 for (ScopStmt &Stmt : *this)
1868 Domain = isl_union_set_add_set(Domain, Stmt.getDomain());
Tobias Grosser5f9a7622012-02-14 14:02:40 +00001869
1870 return Domain;
1871}
1872
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001873__isl_give isl_union_map *Scop::getMustWrites() {
Tobias Grossereeb9f3c2015-05-26 21:37:31 +00001874 isl_union_map *Write = isl_union_map_empty(getParamSpace());
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001875
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001876 for (ScopStmt &Stmt : *this) {
1877 for (MemoryAccess *MA : Stmt) {
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001878 if (!MA->isMustWrite())
1879 continue;
1880
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001881 isl_set *Domain = Stmt.getDomain();
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001882 isl_map *AccessDomain = MA->getAccessRelation();
1883 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
1884 Write = isl_union_map_add_map(Write, AccessDomain);
1885 }
1886 }
1887 return isl_union_map_coalesce(Write);
1888}
1889
1890__isl_give isl_union_map *Scop::getMayWrites() {
Tobias Grossereeb9f3c2015-05-26 21:37:31 +00001891 isl_union_map *Write = isl_union_map_empty(getParamSpace());
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001892
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001893 for (ScopStmt &Stmt : *this) {
1894 for (MemoryAccess *MA : Stmt) {
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001895 if (!MA->isMayWrite())
1896 continue;
1897
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001898 isl_set *Domain = Stmt.getDomain();
Tobias Grosser780ce0f2014-07-11 07:12:10 +00001899 isl_map *AccessDomain = MA->getAccessRelation();
1900 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
1901 Write = isl_union_map_add_map(Write, AccessDomain);
1902 }
1903 }
1904 return isl_union_map_coalesce(Write);
1905}
1906
Tobias Grosser37eb4222014-02-20 21:43:54 +00001907__isl_give isl_union_map *Scop::getWrites() {
Tobias Grossereeb9f3c2015-05-26 21:37:31 +00001908 isl_union_map *Write = isl_union_map_empty(getParamSpace());
Tobias Grosser37eb4222014-02-20 21:43:54 +00001909
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001910 for (ScopStmt &Stmt : *this) {
1911 for (MemoryAccess *MA : Stmt) {
Johannes Doerfertf6752892014-06-13 18:01:45 +00001912 if (!MA->isWrite())
Tobias Grosser37eb4222014-02-20 21:43:54 +00001913 continue;
1914
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001915 isl_set *Domain = Stmt.getDomain();
Johannes Doerfertf6752892014-06-13 18:01:45 +00001916 isl_map *AccessDomain = MA->getAccessRelation();
Tobias Grosser37eb4222014-02-20 21:43:54 +00001917 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
1918 Write = isl_union_map_add_map(Write, AccessDomain);
1919 }
1920 }
1921 return isl_union_map_coalesce(Write);
1922}
1923
1924__isl_give isl_union_map *Scop::getReads() {
Tobias Grosserbc4ef902014-06-28 08:59:38 +00001925 isl_union_map *Read = isl_union_map_empty(getParamSpace());
Tobias Grosser37eb4222014-02-20 21:43:54 +00001926
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001927 for (ScopStmt &Stmt : *this) {
1928 for (MemoryAccess *MA : Stmt) {
Johannes Doerfertf6752892014-06-13 18:01:45 +00001929 if (!MA->isRead())
Tobias Grosser37eb4222014-02-20 21:43:54 +00001930 continue;
1931
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001932 isl_set *Domain = Stmt.getDomain();
Johannes Doerfertf6752892014-06-13 18:01:45 +00001933 isl_map *AccessDomain = MA->getAccessRelation();
Tobias Grosser37eb4222014-02-20 21:43:54 +00001934
1935 AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
1936 Read = isl_union_map_add_map(Read, AccessDomain);
1937 }
1938 }
1939 return isl_union_map_coalesce(Read);
1940}
1941
1942__isl_give isl_union_map *Scop::getSchedule() {
Tobias Grosserbc4ef902014-06-28 08:59:38 +00001943 isl_union_map *Schedule = isl_union_map_empty(getParamSpace());
Tobias Grosser37eb4222014-02-20 21:43:54 +00001944
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001945 for (ScopStmt &Stmt : *this)
1946 Schedule = isl_union_map_add_map(Schedule, Stmt.getSchedule());
Tobias Grosserbc4ef902014-06-28 08:59:38 +00001947
Tobias Grosser37eb4222014-02-20 21:43:54 +00001948 return isl_union_map_coalesce(Schedule);
1949}
1950
1951bool Scop::restrictDomains(__isl_take isl_union_set *Domain) {
1952 bool Changed = false;
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001953 for (ScopStmt &Stmt : *this) {
1954 isl_union_set *StmtDomain = isl_union_set_from_set(Stmt.getDomain());
Tobias Grosser37eb4222014-02-20 21:43:54 +00001955 isl_union_set *NewStmtDomain = isl_union_set_intersect(
1956 isl_union_set_copy(StmtDomain), isl_union_set_copy(Domain));
1957
1958 if (isl_union_set_is_subset(StmtDomain, NewStmtDomain)) {
1959 isl_union_set_free(StmtDomain);
1960 isl_union_set_free(NewStmtDomain);
1961 continue;
1962 }
1963
1964 Changed = true;
1965
1966 isl_union_set_free(StmtDomain);
1967 NewStmtDomain = isl_union_set_coalesce(NewStmtDomain);
1968
1969 if (isl_union_set_is_empty(NewStmtDomain)) {
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001970 Stmt.restrictDomain(isl_set_empty(Stmt.getDomainSpace()));
Tobias Grosser37eb4222014-02-20 21:43:54 +00001971 isl_union_set_free(NewStmtDomain);
1972 } else
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001973 Stmt.restrictDomain(isl_set_from_union_set(NewStmtDomain));
Tobias Grosser37eb4222014-02-20 21:43:54 +00001974 }
1975 isl_union_set_free(Domain);
1976 return Changed;
1977}
1978
Tobias Grosser75805372011-04-29 06:27:02 +00001979ScalarEvolution *Scop::getSE() const { return SE; }
1980
1981bool Scop::isTrivialBB(BasicBlock *BB, TempScop &tempScop) {
1982 if (tempScop.getAccessFunctions(BB))
1983 return false;
1984
1985 return true;
1986}
1987
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001988void Scop::addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop,
1989 const Region &CurRegion,
1990 SmallVectorImpl<Loop *> &NestLoops,
Tobias Grosser54839312015-04-21 11:37:25 +00001991 SmallVectorImpl<unsigned> &ScheduleVec) {
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001992 if (BB) {
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001993 Stmts.emplace_back(*this, tempScop, CurRegion, *BB, NestLoops, ScheduleVec);
1994 StmtMap[BB] = &Stmts.back();
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001995 } else {
Tobias Grosser7c3bad52015-05-27 05:16:57 +00001996 assert(R && "Either basic block or a region expected.");
1997 Stmts.emplace_back(*this, tempScop, CurRegion, *R, NestLoops, ScheduleVec);
1998 auto *Ptr = &Stmts.back();
Johannes Doerfertff9d1982015-02-24 12:00:50 +00001999 for (BasicBlock *BB : R->blocks())
Tobias Grosser7c3bad52015-05-27 05:16:57 +00002000 StmtMap[BB] = Ptr;
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002001 }
2002
Tobias Grosser54839312015-04-21 11:37:25 +00002003 // Increasing the Schedule function is OK for the moment, because
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002004 // we are using a depth first iterator and the program is well structured.
Tobias Grosser54839312015-04-21 11:37:25 +00002005 ++ScheduleVec[NestLoops.size()];
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002006}
2007
Tobias Grosser74394f02013-01-14 22:40:23 +00002008void Scop::buildScop(TempScop &tempScop, const Region &CurRegion,
2009 SmallVectorImpl<Loop *> &NestLoops,
Tobias Grosser54839312015-04-21 11:37:25 +00002010 SmallVectorImpl<unsigned> &ScheduleVec, LoopInfo &LI,
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002011 ScopDetection &SD) {
2012 if (SD.isNonAffineSubRegion(&CurRegion, &getRegion()))
2013 return addScopStmt(nullptr, const_cast<Region *>(&CurRegion), tempScop,
Tobias Grosser54839312015-04-21 11:37:25 +00002014 CurRegion, NestLoops, ScheduleVec);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002015
Tobias Grosser75805372011-04-29 06:27:02 +00002016 Loop *L = castToLoop(CurRegion, LI);
2017
2018 if (L)
2019 NestLoops.push_back(L);
2020
2021 unsigned loopDepth = NestLoops.size();
Tobias Grosser54839312015-04-21 11:37:25 +00002022 assert(ScheduleVec.size() > loopDepth && "Schedule not big enough!");
Tobias Grosser75805372011-04-29 06:27:02 +00002023
2024 for (Region::const_element_iterator I = CurRegion.element_begin(),
Tobias Grosserabfbe632013-02-05 12:09:06 +00002025 E = CurRegion.element_end();
2026 I != E; ++I)
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002027 if (I->isSubRegion()) {
Tobias Grosser654af8f2015-04-21 11:42:01 +00002028 buildScop(tempScop, *I->getNodeAs<Region>(), NestLoops, ScheduleVec, LI,
2029 SD);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002030 } else {
Tobias Grosser75805372011-04-29 06:27:02 +00002031 BasicBlock *BB = I->getNodeAs<BasicBlock>();
2032
2033 if (isTrivialBB(BB, tempScop))
2034 continue;
2035
Tobias Grosser54839312015-04-21 11:37:25 +00002036 addScopStmt(BB, nullptr, tempScop, CurRegion, NestLoops, ScheduleVec);
Tobias Grosser75805372011-04-29 06:27:02 +00002037 }
2038
2039 if (!L)
2040 return;
2041
2042 // Exiting a loop region.
Tobias Grosser54839312015-04-21 11:37:25 +00002043 ScheduleVec[loopDepth] = 0;
Tobias Grosser75805372011-04-29 06:27:02 +00002044 NestLoops.pop_back();
Tobias Grosser54839312015-04-21 11:37:25 +00002045 ++ScheduleVec[loopDepth - 1];
Tobias Grosser75805372011-04-29 06:27:02 +00002046}
2047
Johannes Doerfert7c494212014-10-31 23:13:39 +00002048ScopStmt *Scop::getStmtForBasicBlock(BasicBlock *BB) const {
Tobias Grosser57411e32015-05-27 06:51:34 +00002049 auto StmtMapIt = StmtMap.find(BB);
Johannes Doerfert7c494212014-10-31 23:13:39 +00002050 if (StmtMapIt == StmtMap.end())
2051 return nullptr;
2052 return StmtMapIt->second;
2053}
2054
Tobias Grosser75805372011-04-29 06:27:02 +00002055//===----------------------------------------------------------------------===//
Tobias Grosserb76f38532011-08-20 11:11:25 +00002056ScopInfo::ScopInfo() : RegionPass(ID), scop(0) {
2057 ctx = isl_ctx_alloc();
Tobias Grosser4a8e3562011-12-07 07:42:51 +00002058 isl_options_set_on_error(ctx, ISL_ON_ERROR_ABORT);
Tobias Grosserb76f38532011-08-20 11:11:25 +00002059}
2060
2061ScopInfo::~ScopInfo() {
2062 clear();
2063 isl_ctx_free(ctx);
2064}
2065
Tobias Grosser75805372011-04-29 06:27:02 +00002066void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
Chandler Carruthf5579872015-01-17 14:16:56 +00002067 AU.addRequired<LoopInfoWrapperPass>();
Matt Arsenault8ca36812014-07-19 18:40:17 +00002068 AU.addRequired<RegionInfoPass>();
Tobias Grosser75805372011-04-29 06:27:02 +00002069 AU.addRequired<ScalarEvolution>();
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002070 AU.addRequired<ScopDetection>();
Tobias Grosser75805372011-04-29 06:27:02 +00002071 AU.addRequired<TempScopInfo>();
Johannes Doerfertb164c792014-09-18 11:17:17 +00002072 AU.addRequired<AliasAnalysis>();
Tobias Grosser75805372011-04-29 06:27:02 +00002073 AU.setPreservesAll();
2074}
2075
2076bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
Chandler Carruthf5579872015-01-17 14:16:56 +00002077 LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
Johannes Doerfertb164c792014-09-18 11:17:17 +00002078 AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002079 ScopDetection &SD = getAnalysis<ScopDetection>();
Tobias Grosser75805372011-04-29 06:27:02 +00002080 ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
2081
2082 TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
2083
2084 // This region is no Scop.
2085 if (!tempScop) {
Tobias Grosserc98a8fc2014-11-14 11:12:31 +00002086 scop = nullptr;
Tobias Grosser75805372011-04-29 06:27:02 +00002087 return false;
2088 }
2089
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002090 scop = new Scop(*tempScop, LI, SE, SD, ctx);
Tobias Grosser75805372011-04-29 06:27:02 +00002091
Tobias Grosserd6a50b32015-05-30 06:26:21 +00002092 DEBUG(scop->print(dbgs()));
2093
Johannes Doerfert21aa3dc2014-11-01 01:30:11 +00002094 if (!PollyUseRuntimeAliasChecks) {
2095 // Statistics.
2096 ++ScopFound;
2097 if (scop->getMaxLoopDepth() > 0)
2098 ++RichScopFound;
Johannes Doerfert9143d672014-09-27 11:02:39 +00002099 return false;
Johannes Doerfert21aa3dc2014-11-01 01:30:11 +00002100 }
Johannes Doerfertb164c792014-09-18 11:17:17 +00002101
Johannes Doerfert9143d672014-09-27 11:02:39 +00002102 // If a problem occurs while building the alias groups we need to delete
2103 // this SCoP and pretend it wasn't valid in the first place.
Johannes Doerfert21aa3dc2014-11-01 01:30:11 +00002104 if (scop->buildAliasGroups(AA)) {
2105 // Statistics.
2106 ++ScopFound;
2107 if (scop->getMaxLoopDepth() > 0)
2108 ++RichScopFound;
Johannes Doerfert9143d672014-09-27 11:02:39 +00002109 return false;
Johannes Doerfert21aa3dc2014-11-01 01:30:11 +00002110 }
Johannes Doerfert9143d672014-09-27 11:02:39 +00002111
2112 DEBUG(dbgs()
2113 << "\n\nNOTE: Run time checks for " << scop->getNameStr()
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002114 << " could not be created as the number of parameters involved is too "
Johannes Doerfert9143d672014-09-27 11:02:39 +00002115 "high. The SCoP will be "
2116 "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust the "
Johannes Doerfert6cad9c42015-02-24 16:00:29 +00002117 "maximal number of parameters but be advised that the compile time "
Johannes Doerfert9143d672014-09-27 11:02:39 +00002118 "might increase exponentially.\n\n");
2119
2120 delete scop;
2121 scop = nullptr;
Tobias Grosser75805372011-04-29 06:27:02 +00002122 return false;
2123}
2124
2125char ScopInfo::ID = 0;
2126
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00002127Pass *polly::createScopInfoPass() { return new ScopInfo(); }
2128
Tobias Grosser73600b82011-10-08 00:30:40 +00002129INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops",
2130 "Polly - Create polyhedral description of Scops", false,
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00002131 false);
Johannes Doerfertb164c792014-09-18 11:17:17 +00002132INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
Chandler Carruthf5579872015-01-17 14:16:56 +00002133INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
Matt Arsenault8ca36812014-07-19 18:40:17 +00002134INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00002135INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
Johannes Doerfertff9d1982015-02-24 12:00:50 +00002136INITIALIZE_PASS_DEPENDENCY(ScopDetection);
Tobias Grosser4d96c8d2013-03-23 01:05:07 +00002137INITIALIZE_PASS_DEPENDENCY(TempScopInfo);
Tobias Grosser73600b82011-10-08 00:30:40 +00002138INITIALIZE_PASS_END(ScopInfo, "polly-scops",
2139 "Polly - Create polyhedral description of Scops", false,
2140 false)