blob: 52de6bc087ccb7516eb44ca2617bfe737354d3f0 [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
8using namespace llvm;
9
10namespace SCEVType {
11 enum TYPE {INT, PARAM, IV, INVALID};
12}
13
14struct ValidatorResult {
15 SCEVType::TYPE type;
16
17 ValidatorResult() : type(SCEVType::INVALID) {};
18
19 ValidatorResult(const ValidatorResult &vres) {
20 type = vres.type;
21 };
22
23 ValidatorResult(SCEVType::TYPE type) : type(type) {};
24
25 bool isConstant() {
26 return type == SCEVType::INT || type == SCEVType::PARAM;
27 }
28
29 bool isValid() {
30 return type != SCEVType::INVALID;
31 }
32
33 bool isIV() {
34 return type == SCEVType::IV;
35 }
36
37 bool isINT() {
38 return type == SCEVType::INT;
39 }
40};
41
42/// Check if a SCEV is valid in a SCoP.
43struct SCEVValidator
44 : public SCEVVisitor<SCEVValidator, struct ValidatorResult> {
45private:
46 const Region *R;
47 ScalarEvolution &SE;
48 Value **BaseAddress;
49
50public:
51 SCEVValidator(const Region *R, ScalarEvolution &SE,
52 Value **BaseAddress) : R(R), SE(SE),
53 BaseAddress(BaseAddress) {};
54
55 struct ValidatorResult visitConstant(const SCEVConstant *Constant) {
56 return ValidatorResult(SCEVType::INT);
57 }
58
59 struct ValidatorResult visitTruncateExpr(const SCEVTruncateExpr* Expr) {
60 ValidatorResult Op = visit(Expr->getOperand());
61
62 // We currently do not represent a truncate expression as an affine
63 // expression. If it is constant during Scop execution, we treat it as a
64 // parameter, otherwise we bail out.
65 if (Op.isConstant())
66 return ValidatorResult(SCEVType::PARAM);
67
68 return ValidatorResult (SCEVType::INVALID);
69 }
70
71 struct ValidatorResult visitZeroExtendExpr(const SCEVZeroExtendExpr * Expr) {
72 ValidatorResult Op = visit(Expr->getOperand());
73
74 // We currently do not represent a zero extend expression as an affine
75 // expression. If it is constant during Scop execution, we treat it as a
76 // parameter, otherwise we bail out.
77 if (Op.isConstant())
78 return ValidatorResult (SCEVType::PARAM);
79
80 return ValidatorResult(SCEVType::INVALID);
81 }
82
83 struct ValidatorResult visitSignExtendExpr(const SCEVSignExtendExpr* Expr) {
84 // We currently allow only signed SCEV expressions. In the case of a
85 // signed value, a sign extend is a noop.
86 //
87 // TODO: Reconsider this when we add support for unsigned values.
88 return visit(Expr->getOperand());
89 }
90
91 struct ValidatorResult visitAddExpr(const SCEVAddExpr* Expr) {
92 ValidatorResult Return(SCEVType::INT);
93
94 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
95 ValidatorResult Op = visit(Expr->getOperand(i));
96
97 if (!Op.isValid())
98 return ValidatorResult(SCEVType::INVALID);
99
100 Return.type = std::max(Return.type, Op.type);
101 }
102
103 // TODO: Check for NSW and NUW.
104 return Return;
105 }
106
107 struct ValidatorResult visitMulExpr(const SCEVMulExpr* Expr) {
108 ValidatorResult Return(SCEVType::INT);
109
110 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
111 ValidatorResult Op = visit(Expr->getOperand(i));
112
113 if (Op.type == SCEVType::INT)
114 continue;
115
116 if (Op.type == SCEVType::INVALID || Return.type != SCEVType::INT)
117 return ValidatorResult(SCEVType::INVALID);
118
119 Return.type = Op.type;
120 }
121
122 // TODO: Check for NSW and NUW.
123 return Return;
124 }
125
126 struct ValidatorResult visitUDivExpr(const SCEVUDivExpr* Expr) {
127 ValidatorResult LHS = visit(Expr->getLHS());
128 ValidatorResult RHS = visit(Expr->getRHS());
129
130 // We currently do not represent a unsigned devision as an affine
131 // expression. If the division is constant during Scop execution we treat it
132 // as a parameter, otherwise we bail out.
133 if (LHS.isConstant() && RHS.isConstant())
134 return ValidatorResult(SCEVType::PARAM);
135
136 return ValidatorResult(SCEVType::INVALID);
137 }
138
139 struct ValidatorResult visitAddRecExpr(const SCEVAddRecExpr* Expr) {
140 if (!Expr->isAffine())
141 return ValidatorResult(SCEVType::INVALID);
142
143 ValidatorResult Start = visit(Expr->getStart());
144 ValidatorResult Recurrence = visit(Expr->getStepRecurrence(SE));
145
146 if (!Start.isValid() || !Recurrence.isValid() || Recurrence.isIV())
147 return ValidatorResult(SCEVType::INVALID);
148
149
150 if (!R->contains(Expr->getLoop())) {
151 if (Start.isIV())
152 return ValidatorResult(SCEVType::INVALID);
153 else
154 return ValidatorResult(SCEVType::PARAM);
155 }
156
157 if (!Recurrence.isINT())
158 return ValidatorResult(SCEVType::INVALID);
159
160 return ValidatorResult(SCEVType::IV);
161 }
162
163 struct ValidatorResult visitSMaxExpr(const SCEVSMaxExpr* Expr) {
164 ValidatorResult Return(SCEVType::INT);
165
166 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
167 ValidatorResult Op = visit(Expr->getOperand(i));
168
169 if (!Op.isValid())
170 return ValidatorResult(SCEVType::INVALID);
171
172 Return.type = std::max(Return.type, Op.type);
173 }
174
175 return Return;
176 }
177
178 struct ValidatorResult visitUMaxExpr(const SCEVUMaxExpr* Expr) {
179 // We do not support unsigned operations. If 'Expr' is constant during Scop
180 // execution we treat this as a parameter, otherwise we bail out.
181 for (int i = 0, e = Expr->getNumOperands(); i < e; ++i) {
182 ValidatorResult Op = visit(Expr->getOperand(i));
183
184 if (!Op.isConstant())
185 return ValidatorResult(SCEVType::INVALID);
186 }
187
188 return ValidatorResult(SCEVType::PARAM);
189 }
190
191 ValidatorResult visitUnknown(const SCEVUnknown* Expr) {
192 Value *V = Expr->getValue();
193
194 if (isa<UndefValue>(V))
195 return ValidatorResult(SCEVType::INVALID);
196
197 if (BaseAddress) {
198 if (*BaseAddress)
199 return ValidatorResult(SCEVType::INVALID);
200 else
201 *BaseAddress = V;
202 }
203
204 if (Instruction *I = dyn_cast<Instruction>(Expr->getValue()))
205 if (R->contains(I))
206 return ValidatorResult(SCEVType::INVALID);
207
208 if (BaseAddress)
209 return ValidatorResult(SCEVType::PARAM);
210 else
211 return ValidatorResult(SCEVType::PARAM);
212 }
213};
214
215namespace polly {
216 bool isAffineExpr(const Region *R, const SCEV *Expr, ScalarEvolution &SE,
217 Value **BaseAddress) {
218 if (isa<SCEVCouldNotCompute>(Expr))
219 return false;
220
221 if (BaseAddress)
222 *BaseAddress = NULL;
223
224 SCEVValidator Validator(R, SE, BaseAddress);
225 ValidatorResult Result = Validator.visit(Expr);
226
227 return Result.isValid();
228 }
229}
230
231