blob: 580191fc8e3f18c8892380528986c25a58afdc51 [file] [log] [blame]
Tobias Grosser120db6b2011-11-07 12:58:54 +00001
2#include "polly/Support/SCEVValidator.h"
3
4#include "llvm/Analysis/ScalarEvolution.h"
5#include "llvm/Analysis/ScalarEvolutionExpressions.h"
6#include "llvm/Analysis/RegionInfo.h"
7
Tobias Grosser60b54f12011-11-08 15:41:28 +00008#include <vector>
9
Tobias Grosser120db6b2011-11-07 12:58:54 +000010using namespace llvm;
11
12namespace SCEVType {
Tobias Grosserb1f07c52011-11-17 12:56:17 +000013 /// @brief The type of a SCEV
14 ///
15 /// To check for the validity of a SCEV we assign to each SCEV a type. The
16 /// possible types are INT, PARAM, IV and INVALID. The order of the types is
17 /// important. The subexpressions of SCEV with a type X can only have a type
18 /// that is smaller or equal than X.
19 enum TYPE {
20 // An integer value.
21 INT,
22
23 // An expression that is constant during the execution of the Scop,
24 // but that may depend on parameters unknown at compile time.
25 PARAM,
26
27 // An expression that may change during the execution of the SCoP.
28 IV,
29
30 // An invalid expression.
31 INVALID
32 };
Tobias Grosser120db6b2011-11-07 12:58:54 +000033}
34
Tobias Grosserb1f07c52011-11-17 12:56:17 +000035/// @brief The result the validator returns for a SCEV expression.
Tobias Grosserfa043f02011-11-17 12:56:19 +000036class ValidatorResult {
Tobias Grosserb1f07c52011-11-17 12:56:17 +000037 /// @brief The type of the expression
Tobias Grosseredb8a282011-11-17 12:56:21 +000038 SCEVType::TYPE Type;
Tobias Grosserb1f07c52011-11-17 12:56:17 +000039
40 /// @brief The set of Parameters in the expression.
Tobias Grosser60b54f12011-11-08 15:41:28 +000041 std::vector<const SCEV*> Parameters;
Tobias Grosser120db6b2011-11-07 12:58:54 +000042
Tobias Grosserfa043f02011-11-17 12:56:19 +000043public:
44
Tobias Grosserb1f07c52011-11-17 12:56:17 +000045 /// @brief Create an invalid result.
Tobias Grosseredb8a282011-11-17 12:56:21 +000046 ValidatorResult() : Type(SCEVType::INVALID) {};
Tobias Grosser120db6b2011-11-07 12:58:54 +000047
Tobias Grosserb1f07c52011-11-17 12:56:17 +000048 /// @brief The copy constructor
Tobias Grosseredb8a282011-11-17 12:56:21 +000049 ValidatorResult(const ValidatorResult &Source) {
50 Type = Source.Type;
51 Parameters = Source.Parameters;
Tobias Grosser120db6b2011-11-07 12:58:54 +000052 };
53
Tobias Grosserb1f07c52011-11-17 12:56:17 +000054 /// @brief Construct a result with a certain type and no parameters.
Tobias Grosser371bada2012-03-16 10:16:28 +000055 ValidatorResult(SCEVType::TYPE Type) : Type(Type) {
56 assert(Type != SCEVType::PARAM && "Did you forget to pass the parameter");
57 };
Tobias Grosserb1f07c52011-11-17 12:56:17 +000058
59 /// @brief Construct a result with a certain type and a single parameter.
Tobias Grosseredb8a282011-11-17 12:56:21 +000060 ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
Tobias Grosser60b54f12011-11-08 15:41:28 +000061 Parameters.push_back(Expr);
62 };
Tobias Grosser120db6b2011-11-07 12:58:54 +000063
Tobias Grosserb1f07c52011-11-17 12:56:17 +000064 /// @brief Is the analyzed SCEV constant during the execution of the SCoP.
Tobias Grosser120db6b2011-11-07 12:58:54 +000065 bool isConstant() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000066 return Type == SCEVType::INT || Type == SCEVType::PARAM;
Tobias Grosser120db6b2011-11-07 12:58:54 +000067 }
68
Tobias Grosserb1f07c52011-11-17 12:56:17 +000069 /// @brief Is the analyzed SCEV valid.
Tobias Grosser120db6b2011-11-07 12:58:54 +000070 bool isValid() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000071 return Type != SCEVType::INVALID;
Tobias Grosser120db6b2011-11-07 12:58:54 +000072 }
73
Tobias Grosseredb8a282011-11-17 12:56:21 +000074 /// @brief Is the analyzed SCEV of Type IV.
Tobias Grosser120db6b2011-11-07 12:58:54 +000075 bool isIV() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000076 return Type == SCEVType::IV;
Tobias Grosser120db6b2011-11-07 12:58:54 +000077 }
78
Tobias Grosseredb8a282011-11-17 12:56:21 +000079 /// @brief Is the analyzed SCEV of Type INT.
Tobias Grosser120db6b2011-11-07 12:58:54 +000080 bool isINT() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000081 return Type == SCEVType::INT;
Tobias Grosser120db6b2011-11-07 12:58:54 +000082 }
Tobias Grosser60b54f12011-11-08 15:41:28 +000083
Tobias Grosserfa043f02011-11-17 12:56:19 +000084 /// @brief Get the parameters of this validator result.
85 std::vector<const SCEV*> getParameters() {
86 return Parameters;
87 }
88
Tobias Grosserb1f07c52011-11-17 12:56:17 +000089 /// @brief Add the parameters of Source to this result.
Tobias Grosserfa043f02011-11-17 12:56:19 +000090 void addParamsFrom(class ValidatorResult &Source) {
Tobias Grosserb1f07c52011-11-17 12:56:17 +000091 Parameters.insert(Parameters.end(),
92 Source.Parameters.begin(),
Tobias Grosser60b54f12011-11-08 15:41:28 +000093 Source.Parameters.end());
94 }
Tobias Grosserfa043f02011-11-17 12:56:19 +000095
96 /// @brief Merge a result.
97 ///
Tobias Grosseredb8a282011-11-17 12:56:21 +000098 /// This means to merge the parameters and to set the Type to the most
99 /// specific Type that matches both.
Tobias Grosserfa043f02011-11-17 12:56:19 +0000100 void merge(class ValidatorResult &ToMerge) {
Tobias Grosseredb8a282011-11-17 12:56:21 +0000101 Type = std::max(Type, ToMerge.Type);
Tobias Grosserfa043f02011-11-17 12:56:19 +0000102 addParamsFrom(ToMerge);
103 }
Tobias Grosser540757b2012-03-16 10:12:37 +0000104
105 void print(raw_ostream &OS) {
106 switch (Type) {
107 case SCEVType::INT:
108 OS << "SCEVType::INT\n";
109 break;
110 case SCEVType::PARAM:
111 OS << "SCEVType::PARAM\n";
112 break;
113 case SCEVType::IV:
114 OS << "SCEVType::IV\n";
115 break;
116 case SCEVType::INVALID:
117 OS << "SCEVType::INVALID\n";
118 break;
119 }
120 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000121};
122
Tobias Grosser540757b2012-03-16 10:12:37 +0000123raw_ostream &operator<<(raw_ostream &OS, class ValidatorResult &VR) {
124 VR.print(OS);
125 return OS;
126}
127
Tobias Grosser120db6b2011-11-07 12:58:54 +0000128/// Check if a SCEV is valid in a SCoP.
129struct SCEVValidator
Tobias Grosserfa043f02011-11-17 12:56:19 +0000130 : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000131private:
132 const Region *R;
133 ScalarEvolution &SE;
Tobias Grossere5e171e2011-11-10 12:45:03 +0000134 const Value *BaseAddress;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000135
136public:
137 SCEVValidator(const Region *R, ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000138 const Value *BaseAddress) : R(R), SE(SE),
Tobias Grosser120db6b2011-11-07 12:58:54 +0000139 BaseAddress(BaseAddress) {};
140
Tobias Grosserfa043f02011-11-17 12:56:19 +0000141 class ValidatorResult visitConstant(const SCEVConstant *Constant) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000142 return ValidatorResult(SCEVType::INT);
143 }
144
Tobias Grosserfa043f02011-11-17 12:56:19 +0000145 class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000146 ValidatorResult Op = visit(Expr->getOperand());
147
148 // We currently do not represent a truncate expression as an affine
149 // expression. If it is constant during Scop execution, we treat it as a
150 // parameter, otherwise we bail out.
151 if (Op.isConstant())
Tobias Grosser60b54f12011-11-08 15:41:28 +0000152 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000153
Tobias Grosserfa043f02011-11-17 12:56:19 +0000154 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000155 }
156
Tobias Grosserfa043f02011-11-17 12:56:19 +0000157 class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000158 ValidatorResult Op = visit(Expr->getOperand());
159
160 // We currently do not represent a zero extend expression as an affine
161 // expression. If it is constant during Scop execution, we treat it as a
162 // parameter, otherwise we bail out.
163 if (Op.isConstant())
Tobias Grosserfa043f02011-11-17 12:56:19 +0000164 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000165
166 return ValidatorResult(SCEVType::INVALID);
167 }
168
Tobias Grosserfa043f02011-11-17 12:56:19 +0000169 class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000170 // We currently allow only signed SCEV expressions. In the case of a
171 // signed value, a sign extend is a noop.
172 //
173 // TODO: Reconsider this when we add support for unsigned values.
174 return visit(Expr->getOperand());
175 }
176
Tobias Grosserfa043f02011-11-17 12:56:19 +0000177 class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000178 ValidatorResult Return(SCEVType::INT);
179
180 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
181 ValidatorResult Op = visit(Expr->getOperand(i));
182
183 if (!Op.isValid())
184 return ValidatorResult(SCEVType::INVALID);
185
Tobias Grosserfa043f02011-11-17 12:56:19 +0000186 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000187 }
188
189 // TODO: Check for NSW and NUW.
190 return Return;
191 }
192
Tobias Grosserfa043f02011-11-17 12:56:19 +0000193 class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000194 ValidatorResult Return(SCEVType::INT);
195
196 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
197 ValidatorResult Op = visit(Expr->getOperand(i));
198
Tobias Grosserfa043f02011-11-17 12:56:19 +0000199 if (Op.isINT())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000200 continue;
201
Tobias Grosserfa043f02011-11-17 12:56:19 +0000202 if (!Op.isValid() || !Return.isINT())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000203 return ValidatorResult(SCEVType::INVALID);
204
Tobias Grosserfa043f02011-11-17 12:56:19 +0000205 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000206 }
207
208 // TODO: Check for NSW and NUW.
209 return Return;
210 }
211
Tobias Grosserfa043f02011-11-17 12:56:19 +0000212 class ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000213 ValidatorResult LHS = visit(Expr->getLHS());
214 ValidatorResult RHS = visit(Expr->getRHS());
215
Tobias Grosserf9fbbdf2012-04-09 19:46:05 +0000216 // We currently do not represent an unsigned division as an affine
Tobias Grosser120db6b2011-11-07 12:58:54 +0000217 // expression. If the division is constant during Scop execution we treat it
218 // as a parameter, otherwise we bail out.
219 if (LHS.isConstant() && RHS.isConstant())
Tobias Grosser60b54f12011-11-08 15:41:28 +0000220 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000221
222 return ValidatorResult(SCEVType::INVALID);
223 }
224
Tobias Grosserfa043f02011-11-17 12:56:19 +0000225 class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000226 if (!Expr->isAffine())
227 return ValidatorResult(SCEVType::INVALID);
228
229 ValidatorResult Start = visit(Expr->getStart());
230 ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
231
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000232 if (!Start.isValid() || !Recurrence.isConstant())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000233 return ValidatorResult(SCEVType::INVALID);
234
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000235 if (R->contains(Expr->getLoop())) {
236 if (Recurrence.isINT()) {
237 ValidatorResult Result(SCEVType::IV);
238 Result.addParamsFrom(Start);
239 return Result;
240 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000241
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000242 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000243 }
244
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000245 if (Start.isConstant())
246 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000247
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000248 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000249 }
250
Tobias Grosserfa043f02011-11-17 12:56:19 +0000251 class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
Tobias Grosser371bada2012-03-16 10:16:28 +0000252 ValidatorResult Return(SCEVType::INT, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000253
254 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
255 ValidatorResult Op = visit(Expr->getOperand(i));
256
257 if (!Op.isValid())
258 return ValidatorResult(SCEVType::INVALID);
259
Tobias Grosserfa043f02011-11-17 12:56:19 +0000260 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000261 }
262
263 return Return;
264 }
265
Tobias Grosserfa043f02011-11-17 12:56:19 +0000266 class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000267 // We do not support unsigned operations. If 'Expr' is constant during Scop
268 // execution we treat this as a parameter, otherwise we bail out.
269 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
270 ValidatorResult Op = visit(Expr->getOperand(i));
271
272 if (!Op.isConstant())
273 return ValidatorResult(SCEVType::INVALID);
274 }
275
Tobias Grosser371bada2012-03-16 10:16:28 +0000276 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000277 }
278
Tobias Grosser7ffe4e82011-11-17 12:56:10 +0000279 ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000280 Value *V = Expr->getValue();
281
Tobias Grosser3ec2abc2012-03-16 16:36:47 +0000282 // We currently only support integer types. It may be useful to support
283 // pointer types, e.g. to support code like:
284 //
285 // if (A)
286 // A[i] = 1;
287 //
288 // See test/CodeGen/20120316-InvalidCast.ll
289 if (!Expr->getType()->isIntegerTy())
290 return ValidatorResult(SCEVType::INVALID);
291
Tobias Grosser120db6b2011-11-07 12:58:54 +0000292 if (isa<UndefValue>(V))
293 return ValidatorResult(SCEVType::INVALID);
294
Tobias Grosser120db6b2011-11-07 12:58:54 +0000295 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue()))
296 if (R->contains(I))
297 return ValidatorResult(SCEVType::INVALID);
298
Tobias Grossere5e171e2011-11-10 12:45:03 +0000299 if (BaseAddress == V)
300 return ValidatorResult(SCEVType::INVALID);
301
302 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000303 }
304};
305
306namespace polly {
307 bool isAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000308 const Value *BaseAddress) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000309 if (isa<SCEVCouldNotCompute>(Expr))
310 return false;
311
Tobias Grosser120db6b2011-11-07 12:58:54 +0000312 SCEVValidator Validator(R, SE, BaseAddress);
313 ValidatorResult Result = Validator.visit(Expr);
314
315 return Result.isValid();
316 }
Tobias Grosser60b54f12011-11-08 15:41:28 +0000317
318 std::vector<const SCEV*> getParamsInAffineExpr(const Region *R,
319 const SCEV *Expr,
320 ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000321 const Value *BaseAddress) {
Tobias Grosser60b54f12011-11-08 15:41:28 +0000322 if (isa<SCEVCouldNotCompute>(Expr))
323 return std::vector<const SCEV*>();
324
Tobias Grosser60b54f12011-11-08 15:41:28 +0000325 SCEVValidator Validator(R, SE, BaseAddress);
326 ValidatorResult Result = Validator.visit(Expr);
327
Tobias Grosserfa043f02011-11-17 12:56:19 +0000328 return Result.getParameters();
Tobias Grosser60b54f12011-11-08 15:41:28 +0000329 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000330}
331
332