blob: c32b2eef8814c56407417bb80e39ce2f60e9d74f [file] [log] [blame]
Tobias Grosser120db6b2011-11-07 12:58:54 +00001
2#include "polly/Support/SCEVValidator.h"
Sebastian Pop97cb8132013-03-18 20:21:13 +00003#include "polly/ScopInfo.h"
Tobias Grosserba0d0922015-05-09 09:13:42 +00004#include "llvm/Analysis/RegionInfo.h"
Tobias Grosser120db6b2011-11-07 12:58:54 +00005#include "llvm/Analysis/ScalarEvolution.h"
6#include "llvm/Analysis/ScalarEvolutionExpressions.h"
Chandler Carruth95fef942014-04-22 03:30:19 +00007#include "llvm/Support/Debug.h"
Tobias Grosser60b54f12011-11-08 15:41:28 +00008#include <vector>
9
Tobias Grosser120db6b2011-11-07 12:58:54 +000010using namespace llvm;
Johannes Doerfert09e36972015-10-07 20:17:36 +000011using namespace polly;
Tobias Grosser120db6b2011-11-07 12:58:54 +000012
Chandler Carruth95fef942014-04-22 03:30:19 +000013#define DEBUG_TYPE "polly-scev-validator"
14
Tobias Grosser120db6b2011-11-07 12:58:54 +000015namespace SCEVType {
Tobias Grosserde49b8f2013-02-22 08:21:52 +000016/// @brief The type of a SCEV
17///
18/// To check for the validity of a SCEV we assign to each SCEV a type. The
19/// possible types are INT, PARAM, IV and INVALID. The order of the types is
20/// important. The subexpressions of SCEV with a type X can only have a type
21/// that is smaller or equal than X.
22enum TYPE {
23 // An integer value.
24 INT,
Tobias Grosserb1f07c52011-11-17 12:56:17 +000025
Tobias Grosserde49b8f2013-02-22 08:21:52 +000026 // An expression that is constant during the execution of the Scop,
27 // but that may depend on parameters unknown at compile time.
28 PARAM,
Tobias Grosserb1f07c52011-11-17 12:56:17 +000029
Tobias Grosserde49b8f2013-02-22 08:21:52 +000030 // An expression that may change during the execution of the SCoP.
31 IV,
Tobias Grosserb1f07c52011-11-17 12:56:17 +000032
Tobias Grosserde49b8f2013-02-22 08:21:52 +000033 // An invalid expression.
34 INVALID
35};
Tobias Grosser120db6b2011-11-07 12:58:54 +000036}
37
Tobias Grosserb1f07c52011-11-17 12:56:17 +000038/// @brief The result the validator returns for a SCEV expression.
Tobias Grosserfa043f02011-11-17 12:56:19 +000039class ValidatorResult {
Tobias Grosserb1f07c52011-11-17 12:56:17 +000040 /// @brief The type of the expression
Tobias Grosseredb8a282011-11-17 12:56:21 +000041 SCEVType::TYPE Type;
Tobias Grosserb1f07c52011-11-17 12:56:17 +000042
43 /// @brief The set of Parameters in the expression.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000044 std::vector<const SCEV *> Parameters;
Tobias Grosser120db6b2011-11-07 12:58:54 +000045
Tobias Grosserfa043f02011-11-17 12:56:19 +000046public:
Tobias Grosserb1f07c52011-11-17 12:56:17 +000047 /// @brief The copy constructor
Tobias Grosseredb8a282011-11-17 12:56:21 +000048 ValidatorResult(const ValidatorResult &Source) {
49 Type = Source.Type;
50 Parameters = Source.Parameters;
Tobias Grosserde49b8f2013-02-22 08:21:52 +000051 }
Tobias Grosser120db6b2011-11-07 12:58:54 +000052
Tobias Grosserb1f07c52011-11-17 12:56:17 +000053 /// @brief Construct a result with a certain type and no parameters.
Tobias Grosser371bada2012-03-16 10:16:28 +000054 ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
55 assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
Tobias Grosserde49b8f2013-02-22 08:21:52 +000056 }
Tobias Grosserb1f07c52011-11-17 12:56:17 +000057
58 /// @brief Construct a result with a certain type and a single parameter.
Tobias Grosseredb8a282011-11-17 12:56:21 +000059 ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
Tobias Grosser60b54f12011-11-08 15:41:28 +000060 Parameters.push_back(Expr);
Tobias Grosserde49b8f2013-02-22 08:21:52 +000061 }
Tobias Grosser120db6b2011-11-07 12:58:54 +000062
Tobias Grossereeb776a2012-09-08 14:00:37 +000063 /// @brief Get the type of the ValidatorResult.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000064 SCEVType::TYPE getType() { return Type; }
Tobias Grossereeb776a2012-09-08 14:00:37 +000065
Tobias Grosserb1f07c52011-11-17 12:56:17 +000066 /// @brief Is the analyzed SCEV constant during the execution of the SCoP.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000067 bool isConstant() { return Type == SCEVType::INT || Type == SCEVType::PARAM; }
Tobias Grosser120db6b2011-11-07 12:58:54 +000068
Tobias Grosserb1f07c52011-11-17 12:56:17 +000069 /// @brief Is the analyzed SCEV valid.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000070 bool isValid() { return Type != SCEVType::INVALID; }
Tobias Grosser120db6b2011-11-07 12:58:54 +000071
Tobias Grosseredb8a282011-11-17 12:56:21 +000072 /// @brief Is the analyzed SCEV of Type IV.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000073 bool isIV() { return Type == SCEVType::IV; }
Tobias Grosser120db6b2011-11-07 12:58:54 +000074
Tobias Grosseredb8a282011-11-17 12:56:21 +000075 /// @brief Is the analyzed SCEV of Type INT.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000076 bool isINT() { return Type == SCEVType::INT; }
Tobias Grosser60b54f12011-11-08 15:41:28 +000077
Tobias Grossereeb776a2012-09-08 14:00:37 +000078 /// @brief Is the analyzed SCEV of Type PARAM.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000079 bool isPARAM() { return Type == SCEVType::PARAM; }
Tobias Grossereeb776a2012-09-08 14:00:37 +000080
Tobias Grosserfa043f02011-11-17 12:56:19 +000081 /// @brief Get the parameters of this validator result.
Tobias Grosserde49b8f2013-02-22 08:21:52 +000082 std::vector<const SCEV *> getParameters() { return Parameters; }
Tobias Grosserfa043f02011-11-17 12:56:19 +000083
Tobias Grosserb1f07c52011-11-17 12:56:17 +000084 /// @brief Add the parameters of Source to this result.
Johannes Doerfertecc33a12015-02-26 19:33:42 +000085 void addParamsFrom(const ValidatorResult &Source) {
Tobias Grosserde49b8f2013-02-22 08:21:52 +000086 Parameters.insert(Parameters.end(), Source.Parameters.begin(),
Tobias Grosser60b54f12011-11-08 15:41:28 +000087 Source.Parameters.end());
88 }
Tobias Grosserfa043f02011-11-17 12:56:19 +000089
90 /// @brief Merge a result.
91 ///
Tobias Grosseredb8a282011-11-17 12:56:21 +000092 /// This means to merge the parameters and to set the Type to the most
93 /// specific Type that matches both.
Johannes Doerfertecc33a12015-02-26 19:33:42 +000094 void merge(const ValidatorResult &ToMerge) {
Tobias Grosseredb8a282011-11-17 12:56:21 +000095 Type = std::max(Type, ToMerge.Type);
Tobias Grosserfa043f02011-11-17 12:56:19 +000096 addParamsFrom(ToMerge);
97 }
Tobias Grosser540757b2012-03-16 10:12:37 +000098
99 void print(raw_ostream &OS) {
100 switch (Type) {
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000101 case SCEVType::INT:
102 OS << "SCEVType::INT";
Tobias Grosser540757b2012-03-16 10:12:37 +0000103 break;
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000104 case SCEVType::PARAM:
105 OS << "SCEVType::PARAM";
Tobias Grosser540757b2012-03-16 10:12:37 +0000106 break;
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000107 case SCEVType::IV:
108 OS << "SCEVType::IV";
Tobias Grosser540757b2012-03-16 10:12:37 +0000109 break;
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000110 case SCEVType::INVALID:
111 OS << "SCEVType::INVALID";
Tobias Grosser540757b2012-03-16 10:12:37 +0000112 break;
113 }
114 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000115};
116
Tobias Grosser540757b2012-03-16 10:12:37 +0000117raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
118 VR.print(OS);
119 return OS;
120}
121
Tobias Grosser120db6b2011-11-07 12:58:54 +0000122/// Check if a SCEV is valid in a SCoP.
Tobias Grosser58032cb2013-06-23 01:29:29 +0000123struct SCEVValidator
124 : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000125private:
126 const Region *R;
127 ScalarEvolution &SE;
Tobias Grossere5e171e2011-11-10 12:45:03 +0000128 const Value *BaseAddress;
Johannes Doerfert09e36972015-10-07 20:17:36 +0000129 InvariantLoadsSetTy *ILS;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000130
131public:
Johannes Doerfert09e36972015-10-07 20:17:36 +0000132 SCEVValidator(const Region *R, ScalarEvolution &SE, const Value *BaseAddress,
133 InvariantLoadsSetTy *ILS)
134 : R(R), SE(SE), BaseAddress(BaseAddress), ILS(ILS) {}
Tobias Grosser120db6b2011-11-07 12:58:54 +0000135
Tobias Grosserfa043f02011-11-17 12:56:19 +0000136 class ValidatorResult visitConstant(const SCEVConstant *Constant) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000137 return ValidatorResult(SCEVType::INT);
138 }
139
Tobias Grosserfa043f02011-11-17 12:56:19 +0000140 class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000141 ValidatorResult Op = visit(Expr->getOperand());
142
Tobias Grossereeb776a2012-09-08 14:00:37 +0000143 switch (Op.getType()) {
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000144 case SCEVType::INT:
145 case SCEVType::PARAM:
146 // We currently do not represent a truncate expression as an affine
147 // expression. If it is constant during Scop execution, we treat it as a
148 // parameter.
149 return ValidatorResult(SCEVType::PARAM, Expr);
150 case SCEVType::IV:
151 DEBUG(dbgs() << "INVALID: Truncation of SCEVType::IV expression");
152 return ValidatorResult(SCEVType::INVALID);
153 case SCEVType::INVALID:
154 return Op;
Tobias Grossereeb776a2012-09-08 14:00:37 +0000155 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000156
Tobias Grossereeb776a2012-09-08 14:00:37 +0000157 llvm_unreachable("Unknown SCEVType");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000158 }
159
Tobias Grosserfa043f02011-11-17 12:56:19 +0000160 class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
Tobias Grosserf4daf342014-08-16 09:08:55 +0000161 ValidatorResult Op = visit(Expr->getOperand());
Tobias Grosser120db6b2011-11-07 12:58:54 +0000162
Tobias Grossereeb776a2012-09-08 14:00:37 +0000163 switch (Op.getType()) {
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000164 case SCEVType::INT:
165 case SCEVType::PARAM:
166 // We currently do not represent a truncate expression as an affine
167 // expression. If it is constant during Scop execution, we treat it as a
168 // parameter.
169 return ValidatorResult(SCEVType::PARAM, Expr);
170 case SCEVType::IV:
171 DEBUG(dbgs() << "INVALID: ZeroExtend of SCEVType::IV expression");
172 return ValidatorResult(SCEVType::INVALID);
173 case SCEVType::INVALID:
174 return Op;
Tobias Grossereeb776a2012-09-08 14:00:37 +0000175 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000176
Tobias Grossereeb776a2012-09-08 14:00:37 +0000177 llvm_unreachable("Unknown SCEVType");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000178 }
179
Tobias Grosserfa043f02011-11-17 12:56:19 +0000180 class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000181 // We currently allow only signed SCEV expressions. In the case of a
182 // signed value, a sign extend is a noop.
183 //
184 // TODO: Reconsider this when we add support for unsigned values.
185 return visit(Expr->getOperand());
186 }
187
Tobias Grosserfa043f02011-11-17 12:56:19 +0000188 class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000189 ValidatorResult Return(SCEVType::INT);
190
191 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
192 ValidatorResult Op = visit(Expr->getOperand(i));
Tobias Grosserfa043f02011-11-17 12:56:19 +0000193 Return.merge(Op);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000194
195 // Early exit.
196 if (!Return.isValid())
197 break;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000198 }
199
200 // TODO: Check for NSW and NUW.
201 return Return;
202 }
203
Tobias Grosserfa043f02011-11-17 12:56:19 +0000204 class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000205 ValidatorResult Return(SCEVType::INT);
206
Tobias Grosser3ed26002013-04-14 13:15:59 +0000207 bool HasMultipleParams = false;
208
Tobias Grosser120db6b2011-11-07 12:58:54 +0000209 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
210 ValidatorResult Op = visit(Expr->getOperand(i));
211
Tobias Grosserfa043f02011-11-17 12:56:19 +0000212 if (Op.isINT())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000213 continue;
214
Tobias Grosserecb50922013-04-10 07:42:28 +0000215 if (Op.isPARAM() && Return.isPARAM()) {
Tobias Grossere602a072013-05-07 07:30:56 +0000216 HasMultipleParams = true;
Tobias Grosserecb50922013-04-10 07:42:28 +0000217 continue;
218 }
219
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000220 if ((Op.isIV() || Op.isPARAM()) && !Return.isINT()) {
Tobias Grossereeb776a2012-09-08 14:00:37 +0000221 DEBUG(dbgs() << "INVALID: More than one non-int operand in MulExpr\n"
222 << "\tExpr: " << *Expr << "\n"
223 << "\tPrevious expression type: " << Return << "\n"
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000224 << "\tNext operand (" << Op
225 << "): " << *Expr->getOperand(i) << "\n");
Tobias Grossereeb776a2012-09-08 14:00:37 +0000226
Tobias Grosser120db6b2011-11-07 12:58:54 +0000227 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000228 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000229
Tobias Grosserfa043f02011-11-17 12:56:19 +0000230 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000231 }
232
Tobias Grosser2a586c32015-04-05 14:57:50 +0000233 if (HasMultipleParams && Return.isValid())
Tobias Grosser3ed26002013-04-14 13:15:59 +0000234 return ValidatorResult(SCEVType::PARAM, Expr);
235
Tobias Grosser120db6b2011-11-07 12:58:54 +0000236 // TODO: Check for NSW and NUW.
237 return Return;
238 }
239
Tobias Grosserfa043f02011-11-17 12:56:19 +0000240 class ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000241 ValidatorResult LHS = visit(Expr->getLHS());
242 ValidatorResult RHS = visit(Expr->getRHS());
243
Tobias Grosserf9fbbdf2012-04-09 19:46:05 +0000244 // We currently do not represent an unsigned division as an affine
Tobias Grosser120db6b2011-11-07 12:58:54 +0000245 // expression. If the division is constant during Scop execution we treat it
246 // as a parameter, otherwise we bail out.
247 if (LHS.isConstant() && RHS.isConstant())
Tobias Grosser60b54f12011-11-08 15:41:28 +0000248 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000249
Tobias Grossereeb776a2012-09-08 14:00:37 +0000250 DEBUG(dbgs() << "INVALID: unsigned division of non-constant expressions");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000251 return ValidatorResult(SCEVType::INVALID);
252 }
253
Tobias Grosserfa043f02011-11-17 12:56:19 +0000254 class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
Tobias Grossereeb776a2012-09-08 14:00:37 +0000255 if (!Expr->isAffine()) {
256 DEBUG(dbgs() << "INVALID: AddRec is not affine");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000257 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000258 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000259
260 ValidatorResult Start = visit(Expr->getStart());
261 ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
262
Tobias Grossereeb776a2012-09-08 14:00:37 +0000263 if (!Start.isValid())
264 return Start;
265
266 if (!Recurrence.isValid())
267 return Recurrence;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000268
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000269 if (R->contains(Expr->getLoop())) {
270 if (Recurrence.isINT()) {
271 ValidatorResult Result(SCEVType::IV);
272 Result.addParamsFrom(Start);
273 return Result;
274 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000275
Tobias Grossereeb776a2012-09-08 14:00:37 +0000276 DEBUG(dbgs() << "INVALID: AddRec within scop has non-int"
277 "recurrence part");
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000278 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000279 }
280
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000281 assert(Start.isConstant() && Recurrence.isConstant() &&
282 "Expected 'Start' and 'Recurrence' to be constant");
Tobias Grossere42ddb92013-08-05 15:14:15 +0000283
284 // Directly generate ValidatorResult for Expr if 'start' is zero.
285 if (Expr->getStart()->isZero())
286 return ValidatorResult(SCEVType::PARAM, Expr);
287
288 // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
289 // if 'start' is not zero.
290 const SCEV *ZeroStartExpr = SE.getAddRecExpr(
291 SE.getConstant(Expr->getStart()->getType(), 0),
Johannes Doerfertd5d8f672015-04-26 19:55:21 +0000292 Expr->getStepRecurrence(SE), Expr->getLoop(), Expr->getNoWrapFlags());
Tobias Grossere42ddb92013-08-05 15:14:15 +0000293
294 ValidatorResult ZeroStartResult =
295 ValidatorResult(SCEVType::PARAM, ZeroStartExpr);
296 ZeroStartResult.addParamsFrom(Start);
297
298 return ZeroStartResult;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000299 }
300
Tobias Grosserfa043f02011-11-17 12:56:19 +0000301 class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
Tobias Grosser7b6f9ba2013-12-09 21:51:46 +0000302 ValidatorResult Return(SCEVType::INT);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000303
304 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
305 ValidatorResult Op = visit(Expr->getOperand(i));
306
307 if (!Op.isValid())
Tobias Grossereeb776a2012-09-08 14:00:37 +0000308 return Op;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000309
Tobias Grosserfa043f02011-11-17 12:56:19 +0000310 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000311 }
312
313 return Return;
314 }
315
Tobias Grosserfa043f02011-11-17 12:56:19 +0000316 class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000317 // We do not support unsigned operations. If 'Expr' is constant during Scop
318 // execution we treat this as a parameter, otherwise we bail out.
319 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
320 ValidatorResult Op = visit(Expr->getOperand(i));
321
Tobias Grossereeb776a2012-09-08 14:00:37 +0000322 if (!Op.isConstant()) {
323 DEBUG(dbgs() << "INVALID: UMaxExpr has a non-constant operand");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000324 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000325 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000326 }
327
Tobias Grosser371bada2012-03-16 10:16:28 +0000328 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000329 }
330
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000331 ValidatorResult visitGenericInst(Instruction *I, const SCEV *S) {
332 if (R->contains(I)) {
333 DEBUG(dbgs() << "INVALID: UnknownExpr references an instruction "
334 "within the region\n");
335 return ValidatorResult(SCEVType::INVALID);
336 }
337
338 return ValidatorResult(SCEVType::PARAM, S);
339 }
340
Johannes Doerfert09e36972015-10-07 20:17:36 +0000341 ValidatorResult visitLoadInstruction(Instruction *I, const SCEV *S) {
342 if (R->contains(I) && ILS) {
343 ILS->insert(cast<LoadInst>(I));
344 return ValidatorResult(SCEVType::PARAM, S);
345 }
346
347 return visitGenericInst(I, S);
348 }
349
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000350 ValidatorResult visitSDivInstruction(Instruction *SDiv, const SCEV *S) {
351 assert(SDiv->getOpcode() == Instruction::SDiv &&
352 "Assumed SDiv instruction!");
353
354 auto *Divisor = SDiv->getOperand(1);
355 auto *CI = dyn_cast<ConstantInt>(Divisor);
356 if (!CI)
357 return visitGenericInst(SDiv, S);
358
359 auto *Dividend = SDiv->getOperand(0);
360 auto *DividendSCEV = SE.getSCEV(Dividend);
361 return visit(DividendSCEV);
362 }
363
Tobias Grosser50165ff2015-06-24 04:13:29 +0000364 ValidatorResult visitSRemInstruction(Instruction *SRem, const SCEV *S) {
Johannes Doerfert36255ee2015-09-14 11:14:23 +0000365 assert(SRem->getOpcode() == Instruction::SRem &&
366 "Assumed SRem instruction!");
Tobias Grosser50165ff2015-06-24 04:13:29 +0000367
Johannes Doerfert36255ee2015-09-14 11:14:23 +0000368 auto *Divisor = SRem->getOperand(1);
369 auto *CI = dyn_cast<ConstantInt>(Divisor);
370 if (!CI)
371 return visitGenericInst(SRem, S);
Tobias Grosser50165ff2015-06-24 04:13:29 +0000372
Johannes Doerfert36255ee2015-09-14 11:14:23 +0000373 auto *Dividend = SRem->getOperand(0);
374 auto *DividendSCEV = SE.getSCEV(Dividend);
375 return visit(DividendSCEV);
Tobias Grosser50165ff2015-06-24 04:13:29 +0000376 }
377
Tobias Grosser7ffe4e82011-11-17 12:56:10 +0000378 ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000379 Value *V = Expr->getValue();
380
Johannes Doerfert7ca8dc22015-09-09 14:19:04 +0000381 // TODO: FIXME: IslExprBuilder is not capable of producing valid code
382 // for arbitrary pointer expressions at the moment. Until
383 // this is fixed we disallow pointer expressions completely.
384 if (Expr->getType()->isPointerTy()) {
385 DEBUG(dbgs() << "INVALID: UnknownExpr is a pointer type [FIXME]");
386 return ValidatorResult(SCEVType::INVALID);
387 }
388
389 if (!Expr->getType()->isIntegerTy()) {
390 DEBUG(dbgs() << "INVALID: UnknownExpr is not an integer");
Tobias Grosser3ec2abc2012-03-16 16:36:47 +0000391 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000392 }
Tobias Grosser3ec2abc2012-03-16 16:36:47 +0000393
Tobias Grossereeb776a2012-09-08 14:00:37 +0000394 if (isa<UndefValue>(V)) {
395 DEBUG(dbgs() << "INVALID: UnknownExpr references an undef value");
Tobias Grosser120db6b2011-11-07 12:58:54 +0000396 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000397 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000398
Tobias Grossereeb776a2012-09-08 14:00:37 +0000399 if (BaseAddress == V) {
400 DEBUG(dbgs() << "INVALID: UnknownExpr references BaseAddress\n");
Tobias Grossere5e171e2011-11-10 12:45:03 +0000401 return ValidatorResult(SCEVType::INVALID);
Tobias Grossereeb776a2012-09-08 14:00:37 +0000402 }
Tobias Grossere5e171e2011-11-10 12:45:03 +0000403
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000404 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
405 switch (I->getOpcode()) {
Johannes Doerfert09e36972015-10-07 20:17:36 +0000406 case Instruction::Load:
407 return visitLoadInstruction(I, Expr);
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000408 case Instruction::SDiv:
409 return visitSDivInstruction(I, Expr);
Tobias Grosser50165ff2015-06-24 04:13:29 +0000410 case Instruction::SRem:
411 return visitSRemInstruction(I, Expr);
Johannes Doerfertb9d18882015-02-11 14:54:50 +0000412 default:
413 return visitGenericInst(I, Expr);
414 }
415 }
416
Tobias Grossere5e171e2011-11-10 12:45:03 +0000417 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000418 }
419};
420
Sebastian Pop97cb8132013-03-18 20:21:13 +0000421/// @brief Check whether a SCEV refers to an SSA name defined inside a region.
422///
Tobias Grosser58032cb2013-06-23 01:29:29 +0000423struct SCEVInRegionDependences
424 : public SCEVVisitor<SCEVInRegionDependences, bool> {
Sebastian Pop97cb8132013-03-18 20:21:13 +0000425public:
Sebastian Pop97cb8132013-03-18 20:21:13 +0000426 /// Returns true when the SCEV has SSA names defined in region R.
427 static bool hasDependences(const SCEV *S, const Region *R) {
428 SCEVInRegionDependences Ignore(R);
429 return Ignore.visit(S);
430 }
431
432 SCEVInRegionDependences(const Region *R) : R(R) {}
433
434 bool visit(const SCEV *Expr) {
435 return SCEVVisitor<SCEVInRegionDependences, bool>::visit(Expr);
436 }
437
438 bool visitConstant(const SCEVConstant *Constant) { return false; }
439
440 bool visitTruncateExpr(const SCEVTruncateExpr *Expr) {
441 return visit(Expr->getOperand());
442 }
443
444 bool visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
445 return visit(Expr->getOperand());
446 }
447
448 bool visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
449 return visit(Expr->getOperand());
450 }
451
452 bool visitAddExpr(const SCEVAddExpr *Expr) {
453 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
454 if (visit(Expr->getOperand(i)))
455 return true;
456
457 return false;
458 }
459
460 bool visitMulExpr(const SCEVMulExpr *Expr) {
461 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i)
462 if (visit(Expr->getOperand(i)))
463 return true;
464
465 return false;
466 }
467
468 bool visitUDivExpr(const SCEVUDivExpr *Expr) {
469 if (visit(Expr->getLHS()))
470 return true;
471
472 if (visit(Expr->getRHS()))
473 return true;
474
475 return false;
476 }
477
478 bool visitAddRecExpr(const SCEVAddRecExpr *Expr) {
479 if (visit(Expr->getStart()))
480 return true;
481
482 for (size_t i = 0; i < Expr->getNumOperands(); ++i)
483 if (visit(Expr->getOperand(i)))
484 return true;
485
486 return false;
487 }
488
489 bool visitSMaxExpr(const SCEVSMaxExpr *Expr) {
490 for (size_t i = 0; i < Expr->getNumOperands(); ++i)
491 if (visit(Expr->getOperand(i)))
492 return true;
493
494 return false;
495 }
496
497 bool visitUMaxExpr(const SCEVUMaxExpr *Expr) {
498 for (size_t i = 0; i < Expr->getNumOperands(); ++i)
499 if (visit(Expr->getOperand(i)))
500 return true;
501
502 return false;
503 }
504
505 bool visitUnknown(const SCEVUnknown *Expr) {
506 Instruction *Inst = dyn_cast<Instruction>(Expr->getValue());
507
508 // Return true when Inst is defined inside the region R.
509 if (Inst && R->contains(Inst))
510 return true;
511
512 return false;
513 }
514
515private:
516 const Region *R;
517};
518
Tobias Grosser120db6b2011-11-07 12:58:54 +0000519namespace polly {
Tobias Grossere3c05582014-11-15 21:32:53 +0000520/// Find all loops referenced in SCEVAddRecExprs.
521class SCEVFindLoops {
522 SetVector<const Loop *> &Loops;
523
524public:
525 SCEVFindLoops(SetVector<const Loop *> &Loops) : Loops(Loops) {}
526
527 bool follow(const SCEV *S) {
528 if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S))
529 Loops.insert(AddRec->getLoop());
530 return true;
531 }
532 bool isDone() { return false; }
533};
534
535void findLoops(const SCEV *Expr, SetVector<const Loop *> &Loops) {
536 SCEVFindLoops FindLoops(Loops);
537 SCEVTraversal<SCEVFindLoops> ST(FindLoops);
538 ST.visitAll(Expr);
539}
540
541/// Find all values referenced in SCEVUnknowns.
542class SCEVFindValues {
543 SetVector<Value *> &Values;
544
545public:
546 SCEVFindValues(SetVector<Value *> &Values) : Values(Values) {}
547
548 bool follow(const SCEV *S) {
549 if (const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(S))
550 Values.insert(Unknown->getValue());
551 return true;
552 }
553 bool isDone() { return false; }
554};
555
556void findValues(const SCEV *Expr, SetVector<Value *> &Values) {
557 SCEVFindValues FindValues(Values);
558 SCEVTraversal<SCEVFindValues> ST(FindValues);
559 ST.visitAll(Expr);
560}
561
Tobias Grosser4d96c8d2013-03-23 01:05:07 +0000562bool hasScalarDepsInsideRegion(const SCEV *Expr, const Region *R) {
563 return SCEVInRegionDependences::hasDependences(Expr, R);
564}
Sebastian Pop97cb8132013-03-18 20:21:13 +0000565
Tobias Grosser4d96c8d2013-03-23 01:05:07 +0000566bool isAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE,
Johannes Doerfert09e36972015-10-07 20:17:36 +0000567 const Value *BaseAddress, InvariantLoadsSetTy *ILS) {
Tobias Grosser4d96c8d2013-03-23 01:05:07 +0000568 if (isa<SCEVCouldNotCompute>(Expr))
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000569 return false;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000570
Johannes Doerfert09e36972015-10-07 20:17:36 +0000571 SCEVValidator Validator(R, SE, BaseAddress, ILS);
Tobias Grosserf084edd2014-10-22 23:00:03 +0000572 DEBUG({
573 dbgs() << "\n";
574 dbgs() << "Expr: " << *Expr << "\n";
575 dbgs() << "Region: " << R->getNameStr() << "\n";
576 dbgs() << " -> ";
577 });
Tobias Grossereeb776a2012-09-08 14:00:37 +0000578
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000579 ValidatorResult Result = Validator.visit(Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000580
Tobias Grosserf084edd2014-10-22 23:00:03 +0000581 DEBUG({
582 if (Result.isValid())
583 dbgs() << "VALID\n";
584 dbgs() << "\n";
585 });
Tobias Grossereeb776a2012-09-08 14:00:37 +0000586
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000587 return Result.isValid();
588}
Tobias Grosser60b54f12011-11-08 15:41:28 +0000589
Johannes Doerfert2af10e22015-11-12 03:25:01 +0000590static bool isAffineParamExpr(Value *V, const Region *R, ScalarEvolution &SE,
591 std::vector<const SCEV *> &Params) {
592 auto *E = SE.getSCEV(V);
593 if (isa<SCEVCouldNotCompute>(E))
594 return false;
595
596 SCEVValidator Validator(R, SE, nullptr, nullptr);
597 ValidatorResult Result = Validator.visit(E);
598 if (!Result.isConstant())
599 return false;
600
601 auto ResultParams = Result.getParameters();
602 Params.insert(Params.end(), ResultParams.begin(), ResultParams.end());
603
604 return true;
605}
606
607bool isAffineParamConstraint(Value *V, const Region *R, ScalarEvolution &SE,
608 std::vector<const SCEV *> &Params, bool OrExpr) {
609 if (auto *ICmp = dyn_cast<ICmpInst>(V)) {
610 return isAffineParamConstraint(ICmp->getOperand(0), R, SE, Params, true) &&
611 isAffineParamConstraint(ICmp->getOperand(1), R, SE, Params, true);
612 } else if (auto *BinOp = dyn_cast<BinaryOperator>(V)) {
613 auto Opcode = BinOp->getOpcode();
614 if (Opcode == Instruction::And || Opcode == Instruction::Or)
615 return isAffineParamConstraint(BinOp->getOperand(0), R, SE, Params,
616 false) &&
617 isAffineParamConstraint(BinOp->getOperand(1), R, SE, Params,
618 false);
619 /* Fall through */
620 }
621
622 if (!OrExpr)
623 return false;
624
625 return isAffineParamExpr(V, R, SE, Params);
626}
627
Tobias Grossere602a072013-05-07 07:30:56 +0000628std::vector<const SCEV *> getParamsInAffineExpr(const Region *R,
629 const SCEV *Expr,
630 ScalarEvolution &SE,
631 const Value *BaseAddress) {
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000632 if (isa<SCEVCouldNotCompute>(Expr))
633 return std::vector<const SCEV *>();
Tobias Grosser60b54f12011-11-08 15:41:28 +0000634
Johannes Doerfert09e36972015-10-07 20:17:36 +0000635 InvariantLoadsSetTy ILS;
636 SCEVValidator Validator(R, SE, BaseAddress, &ILS);
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000637 ValidatorResult Result = Validator.visit(Expr);
Johannes Doerfert89830312015-05-03 16:03:01 +0000638 assert(Result.isValid() && "Requested parameters for an invalid SCEV!");
Tobias Grosser60b54f12011-11-08 15:41:28 +0000639
Tobias Grosserde49b8f2013-02-22 08:21:52 +0000640 return Result.getParameters();
641}
Johannes Doerfertbe409962015-03-29 20:45:09 +0000642
Johannes Doerfert965edde62016-02-14 22:30:56 +0000643std::pair<const SCEVConstant *, const SCEV *>
Johannes Doerfertbe409962015-03-29 20:45:09 +0000644extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
645
Johannes Doerfert965edde62016-02-14 22:30:56 +0000646 auto *LeftOver = SE.getConstant(S->getType(), 1);
647 auto *ConstPart = cast<SCEVConstant>(SE.getConstant(S->getType(), 1));
Johannes Doerfertbe409962015-03-29 20:45:09 +0000648
Johannes Doerfert965edde62016-02-14 22:30:56 +0000649 if (auto *Constant = dyn_cast<SCEVConstant>(S))
650 return std::make_pair(Constant, LeftOver);
651
652 auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
653 if (AddRec) {
654 auto *StartExpr = AddRec->getStart();
655 if (StartExpr->isZero()) {
656 auto StepPair = extractConstantFactor(AddRec->getStepRecurrence(SE), SE);
657 auto *LeftOverAddRec =
658 SE.getAddRecExpr(StartExpr, StepPair.second, AddRec->getLoop(),
659 AddRec->getNoWrapFlags());
660 return std::make_pair(StepPair.first, LeftOverAddRec);
661 }
662 return std::make_pair(ConstPart, S);
663 }
664
665 auto *Mul = dyn_cast<SCEVMulExpr>(S);
666 if (!Mul)
Johannes Doerfertbe409962015-03-29 20:45:09 +0000667 return std::make_pair(ConstPart, S);
668
Johannes Doerfert965edde62016-02-14 22:30:56 +0000669 for (auto *Op : Mul->operands())
Johannes Doerfertbe409962015-03-29 20:45:09 +0000670 if (isa<SCEVConstant>(Op))
Johannes Doerfert965edde62016-02-14 22:30:56 +0000671 ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));
Johannes Doerfertbe409962015-03-29 20:45:09 +0000672 else
673 LeftOver = SE.getMulExpr(LeftOver, Op);
674
675 return std::make_pair(ConstPart, LeftOver);
676}
Tobias Grosser120db6b2011-11-07 12:58:54 +0000677}