blob: 0b87e9e755e49dab2c730a943e17c6d244e6eb74 [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 Grosseredb8a282011-11-17 12:56:21 +000055 ValidatorResult(SCEVType::TYPE Type) : Type(Type) {};
Tobias Grosserb1f07c52011-11-17 12:56:17 +000056
57 /// @brief Construct a result with a certain type and a single parameter.
Tobias Grosseredb8a282011-11-17 12:56:21 +000058 ValidatorResult(SCEVType::TYPE Type, const SCEV *Expr) : Type(Type) {
Tobias Grosser60b54f12011-11-08 15:41:28 +000059 Parameters.push_back(Expr);
60 };
Tobias Grosser120db6b2011-11-07 12:58:54 +000061
Tobias Grosserb1f07c52011-11-17 12:56:17 +000062 /// @brief Is the analyzed SCEV constant during the execution of the SCoP.
Tobias Grosser120db6b2011-11-07 12:58:54 +000063 bool isConstant() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000064 return Type == SCEVType::INT || Type == SCEVType::PARAM;
Tobias Grosser120db6b2011-11-07 12:58:54 +000065 }
66
Tobias Grosserb1f07c52011-11-17 12:56:17 +000067 /// @brief Is the analyzed SCEV valid.
Tobias Grosser120db6b2011-11-07 12:58:54 +000068 bool isValid() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000069 return Type != SCEVType::INVALID;
Tobias Grosser120db6b2011-11-07 12:58:54 +000070 }
71
Tobias Grosseredb8a282011-11-17 12:56:21 +000072 /// @brief Is the analyzed SCEV of Type IV.
Tobias Grosser120db6b2011-11-07 12:58:54 +000073 bool isIV() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000074 return Type == SCEVType::IV;
Tobias Grosser120db6b2011-11-07 12:58:54 +000075 }
76
Tobias Grosseredb8a282011-11-17 12:56:21 +000077 /// @brief Is the analyzed SCEV of Type INT.
Tobias Grosser120db6b2011-11-07 12:58:54 +000078 bool isINT() {
Tobias Grosseredb8a282011-11-17 12:56:21 +000079 return Type == SCEVType::INT;
Tobias Grosser120db6b2011-11-07 12:58:54 +000080 }
Tobias Grosser60b54f12011-11-08 15:41:28 +000081
Tobias Grosserfa043f02011-11-17 12:56:19 +000082 /// @brief Get the parameters of this validator result.
83 std::vector<const SCEV*> getParameters() {
84 return Parameters;
85 }
86
Tobias Grosserb1f07c52011-11-17 12:56:17 +000087 /// @brief Add the parameters of Source to this result.
Tobias Grosserfa043f02011-11-17 12:56:19 +000088 void addParamsFrom(class ValidatorResult &Source) {
Tobias Grosserb1f07c52011-11-17 12:56:17 +000089 Parameters.insert(Parameters.end(),
90 Source.Parameters.begin(),
Tobias Grosser60b54f12011-11-08 15:41:28 +000091 Source.Parameters.end());
92 }
Tobias Grosserfa043f02011-11-17 12:56:19 +000093
94 /// @brief Merge a result.
95 ///
Tobias Grosseredb8a282011-11-17 12:56:21 +000096 /// This means to merge the parameters and to set the Type to the most
97 /// specific Type that matches both.
Tobias Grosserfa043f02011-11-17 12:56:19 +000098 void merge(class ValidatorResult &ToMerge) {
Tobias Grosseredb8a282011-11-17 12:56:21 +000099 Type = std::max(Type, ToMerge.Type);
Tobias Grosserfa043f02011-11-17 12:56:19 +0000100 addParamsFrom(ToMerge);
101 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000102};
103
104/// Check if a SCEV is valid in a SCoP.
105struct SCEVValidator
Tobias Grosserfa043f02011-11-17 12:56:19 +0000106 : public SCEVVisitor<SCEVValidator, class ValidatorResult> {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000107private:
108 const Region *R;
109 ScalarEvolution &SE;
Tobias Grossere5e171e2011-11-10 12:45:03 +0000110 const Value *BaseAddress;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000111
112public:
113 SCEVValidator(const Region *R, ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000114 const Value *BaseAddress) : R(R), SE(SE),
Tobias Grosser120db6b2011-11-07 12:58:54 +0000115 BaseAddress(BaseAddress) {};
116
Tobias Grosserfa043f02011-11-17 12:56:19 +0000117 class ValidatorResult visitConstant(const SCEVConstant *Constant) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000118 return ValidatorResult(SCEVType::INT);
119 }
120
Tobias Grosserfa043f02011-11-17 12:56:19 +0000121 class ValidatorResult visitTruncateExpr(const SCEVTruncateExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000122 ValidatorResult Op = visit(Expr->getOperand());
123
124 // We currently do not represent a truncate expression as an affine
125 // expression. If it is constant during Scop execution, we treat it as a
126 // parameter, otherwise we bail out.
127 if (Op.isConstant())
Tobias Grosser60b54f12011-11-08 15:41:28 +0000128 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000129
Tobias Grosserfa043f02011-11-17 12:56:19 +0000130 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000131 }
132
Tobias Grosserfa043f02011-11-17 12:56:19 +0000133 class ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000134 ValidatorResult Op = visit(Expr->getOperand());
135
136 // We currently do not represent a zero extend expression as an affine
137 // expression. If it is constant during Scop execution, we treat it as a
138 // parameter, otherwise we bail out.
139 if (Op.isConstant())
Tobias Grosserfa043f02011-11-17 12:56:19 +0000140 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000141
142 return ValidatorResult(SCEVType::INVALID);
143 }
144
Tobias Grosserfa043f02011-11-17 12:56:19 +0000145 class ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000146 // We currently allow only signed SCEV expressions. In the case of a
147 // signed value, a sign extend is a noop.
148 //
149 // TODO: Reconsider this when we add support for unsigned values.
150 return visit(Expr->getOperand());
151 }
152
Tobias Grosserfa043f02011-11-17 12:56:19 +0000153 class ValidatorResult visitAddExpr(const SCEVAddExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000154 ValidatorResult Return(SCEVType::INT);
155
156 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
157 ValidatorResult Op = visit(Expr->getOperand(i));
158
159 if (!Op.isValid())
160 return ValidatorResult(SCEVType::INVALID);
161
Tobias Grosserfa043f02011-11-17 12:56:19 +0000162 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000163 }
164
165 // TODO: Check for NSW and NUW.
166 return Return;
167 }
168
Tobias Grosserfa043f02011-11-17 12:56:19 +0000169 class ValidatorResult visitMulExpr(const SCEVMulExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000170 ValidatorResult Return(SCEVType::INT);
171
172 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
173 ValidatorResult Op = visit(Expr->getOperand(i));
174
Tobias Grosserfa043f02011-11-17 12:56:19 +0000175 if (Op.isINT())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000176 continue;
177
Tobias Grosserfa043f02011-11-17 12:56:19 +0000178 if (!Op.isValid() || !Return.isINT())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000179 return ValidatorResult(SCEVType::INVALID);
180
Tobias Grosserfa043f02011-11-17 12:56:19 +0000181 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000182 }
183
184 // TODO: Check for NSW and NUW.
185 return Return;
186 }
187
Tobias Grosserfa043f02011-11-17 12:56:19 +0000188 class ValidatorResult visitUDivExpr(const SCEVUDivExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000189 ValidatorResult LHS = visit(Expr->getLHS());
190 ValidatorResult RHS = visit(Expr->getRHS());
191
Tobias Grosser2a7cd942011-11-17 12:56:12 +0000192 // We currently do not represent an unsigned devision as an affine
Tobias Grosser120db6b2011-11-07 12:58:54 +0000193 // expression. If the division is constant during Scop execution we treat it
194 // as a parameter, otherwise we bail out.
195 if (LHS.isConstant() && RHS.isConstant())
Tobias Grosser60b54f12011-11-08 15:41:28 +0000196 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000197
198 return ValidatorResult(SCEVType::INVALID);
199 }
200
Tobias Grosserfa043f02011-11-17 12:56:19 +0000201 class ValidatorResult visitAddRecExpr(const SCEVAddRecExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000202 if (!Expr->isAffine())
203 return ValidatorResult(SCEVType::INVALID);
204
205 ValidatorResult Start = visit(Expr->getStart());
206 ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
207
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000208 if (!Start.isValid() || !Recurrence.isConstant())
Tobias Grosser120db6b2011-11-07 12:58:54 +0000209 return ValidatorResult(SCEVType::INVALID);
210
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000211 if (R->contains(Expr->getLoop())) {
212 if (Recurrence.isINT()) {
213 ValidatorResult Result(SCEVType::IV);
214 Result.addParamsFrom(Start);
215 return Result;
216 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000217
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000218 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000219 }
220
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000221 if (Start.isConstant())
222 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000223
Tobias Grosserbcc0a0d2011-11-17 12:56:14 +0000224 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000225 }
226
Tobias Grosserfa043f02011-11-17 12:56:19 +0000227 class ValidatorResult visitSMaxExpr(const SCEVSMaxExpr *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000228 ValidatorResult Return(SCEVType::INT);
229
230 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
231 ValidatorResult Op = visit(Expr->getOperand(i));
232
233 if (!Op.isValid())
234 return ValidatorResult(SCEVType::INVALID);
235
Tobias Grosserfa043f02011-11-17 12:56:19 +0000236 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000237 }
238
239 return Return;
240 }
241
Tobias Grosserfa043f02011-11-17 12:56:19 +0000242 class ValidatorResult visitUMaxExpr(const SCEVUMaxExpr *Expr) {
Tobias Grosser60b54f12011-11-08 15:41:28 +0000243 ValidatorResult Return(SCEVType::PARAM);
244
Tobias Grosser120db6b2011-11-07 12:58:54 +0000245 // We do not support unsigned operations. If 'Expr' is constant during Scop
246 // execution we treat this as a parameter, otherwise we bail out.
247 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
248 ValidatorResult Op = visit(Expr->getOperand(i));
249
250 if (!Op.isConstant())
251 return ValidatorResult(SCEVType::INVALID);
Tobias Grosser60b54f12011-11-08 15:41:28 +0000252
Tobias Grosserfa043f02011-11-17 12:56:19 +0000253 Return.merge(Op);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000254 }
255
Tobias Grosser60b54f12011-11-08 15:41:28 +0000256 return Return;
Tobias Grosser120db6b2011-11-07 12:58:54 +0000257 }
258
Tobias Grosser7ffe4e82011-11-17 12:56:10 +0000259 ValidatorResult visitUnknown(const SCEVUnknown *Expr) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000260 Value *V = Expr->getValue();
261
262 if (isa<UndefValue>(V))
263 return ValidatorResult(SCEVType::INVALID);
264
Tobias Grosser120db6b2011-11-07 12:58:54 +0000265 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue()))
266 if (R->contains(I))
267 return ValidatorResult(SCEVType::INVALID);
268
Tobias Grossere5e171e2011-11-10 12:45:03 +0000269 if (BaseAddress == V)
270 return ValidatorResult(SCEVType::INVALID);
271
272 return ValidatorResult(SCEVType::PARAM, Expr);
Tobias Grosser120db6b2011-11-07 12:58:54 +0000273 }
274};
275
276namespace polly {
277 bool isAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000278 const Value *BaseAddress) {
Tobias Grosser120db6b2011-11-07 12:58:54 +0000279 if (isa<SCEVCouldNotCompute>(Expr))
280 return false;
281
Tobias Grosser120db6b2011-11-07 12:58:54 +0000282 SCEVValidator Validator(R, SE, BaseAddress);
283 ValidatorResult Result = Validator.visit(Expr);
284
285 return Result.isValid();
286 }
Tobias Grosser60b54f12011-11-08 15:41:28 +0000287
288 std::vector<const SCEV*> getParamsInAffineExpr(const Region *R,
289 const SCEV *Expr,
290 ScalarEvolution &SE,
Tobias Grossere5e171e2011-11-10 12:45:03 +0000291 const Value *BaseAddress) {
Tobias Grosser60b54f12011-11-08 15:41:28 +0000292 if (isa<SCEVCouldNotCompute>(Expr))
293 return std::vector<const SCEV*>();
294
Tobias Grosser60b54f12011-11-08 15:41:28 +0000295 SCEVValidator Validator(R, SE, BaseAddress);
296 ValidatorResult Result = Validator.visit(Expr);
297
Tobias Grosserfa043f02011-11-17 12:56:19 +0000298 return Result.getParameters();
Tobias Grosser60b54f12011-11-08 15:41:28 +0000299 }
Tobias Grosser120db6b2011-11-07 12:58:54 +0000300}
301
302