1 //===------ IslExprBuilder.cpp ----- Code generate isl AST expressions ----===//
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 //===----------------------------------------------------------------------===//
11 
12 #include "polly/CodeGen/IslExprBuilder.h"
13 
14 #include "polly/Support/GICHelper.h"
15 
16 #include "llvm/Support/Debug.h"
17 
18 using namespace llvm;
19 using namespace polly;
20 
21 Type *IslExprBuilder::getWidestType(Type *T1, Type *T2) {
22   assert(isa<IntegerType>(T1) && isa<IntegerType>(T2));
23 
24   if (T1->getPrimitiveSizeInBits() < T2->getPrimitiveSizeInBits())
25     return T2;
26   else
27     return T1;
28 }
29 
30 Value *IslExprBuilder::createOpUnary(__isl_take isl_ast_expr *Expr) {
31   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_minus &&
32          "Unsupported unary operation");
33 
34   Value *V;
35   Type *MaxType = getType(Expr);
36 
37   V = create(isl_ast_expr_get_op_arg(Expr, 0));
38   MaxType = getWidestType(MaxType, V->getType());
39 
40   if (MaxType != V->getType())
41     V = Builder.CreateSExt(V, MaxType);
42 
43   isl_ast_expr_free(Expr);
44   return Builder.CreateNSWNeg(V);
45 }
46 
47 Value *IslExprBuilder::createOpNAry(__isl_take isl_ast_expr *Expr) {
48   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
49          "isl ast expression not of type isl_ast_op");
50   assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
51          "We need at least two operands in an n-ary operation");
52 
53   Value *V;
54 
55   V = create(isl_ast_expr_get_op_arg(Expr, 0));
56 
57   for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr); ++i) {
58     Value *OpV;
59     OpV = create(isl_ast_expr_get_op_arg(Expr, i));
60 
61     Type *Ty = getWidestType(V->getType(), OpV->getType());
62 
63     if (Ty != OpV->getType())
64       OpV = Builder.CreateSExt(OpV, Ty);
65 
66     if (Ty != V->getType())
67       V = Builder.CreateSExt(V, Ty);
68 
69     switch (isl_ast_expr_get_op_type(Expr)) {
70     default:
71       llvm_unreachable("This is no n-ary isl ast expression");
72 
73     case isl_ast_op_max: {
74       Value *Cmp = Builder.CreateICmpSGT(V, OpV);
75       V = Builder.CreateSelect(Cmp, V, OpV);
76       continue;
77     }
78     case isl_ast_op_min: {
79       Value *Cmp = Builder.CreateICmpSLT(V, OpV);
80       V = Builder.CreateSelect(Cmp, V, OpV);
81       continue;
82     }
83     }
84   }
85 
86   // TODO: We can truncate the result, if it fits into a smaller type. This can
87   // help in cases where we have larger operands (e.g. i67) but the result is
88   // known to fit into i64. Without the truncation, the larger i67 type may
89   // force all subsequent operations to be performed on a non-native type.
90   isl_ast_expr_free(Expr);
91   return V;
92 }
93 
94 Value *IslExprBuilder::createOpAccess(isl_ast_expr *Expr) {
95   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
96          "isl ast expression not of type isl_ast_op");
97   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_access &&
98          "not an access isl ast expression");
99   assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
100          "We need at least two operands to create a member access.");
101 
102   // TODO: Support for multi-dimensional array.
103   assert(isl_ast_expr_get_op_n_arg(Expr) == 2 &&
104          "Multidimensional access functions are not supported yet");
105 
106   Value *Base, *IndexOp, *Zero, *Access;
107   SmallVector<Value *, 4> Indices;
108   Type *PtrElTy;
109 
110   Base = create(isl_ast_expr_get_op_arg(Expr, 0));
111   assert(Base->getType()->isPointerTy() && "Access base should be a pointer");
112 
113   IndexOp = create(isl_ast_expr_get_op_arg(Expr, 1));
114   assert(IndexOp->getType()->isIntegerTy() &&
115          "Access index should be an integer");
116   Zero = ConstantInt::getNullValue(IndexOp->getType());
117 
118   // If base is a array type like,
119   //   int A[N][M][K];
120   // we have to adjust the GEP. The easiest way is to transform accesses like,
121   //   A[i][j][k]
122   // into equivalent ones like,
123   //   A[0][0][ i*N*M + j*M + k]
124   // because SCEV already folded the "peudo dimensions" into one. Thus our index
125   // operand will be 'i*N*M + j*M + k' anyway.
126   PtrElTy = Base->getType()->getPointerElementType();
127   while (PtrElTy->isArrayTy()) {
128     Indices.push_back(Zero);
129     PtrElTy = PtrElTy->getArrayElementType();
130   }
131 
132   Indices.push_back(IndexOp);
133   assert((PtrElTy->isIntOrIntVectorTy() || PtrElTy->isFPOrFPVectorTy()) &&
134          "We do not yet change the type of the access base during code "
135          "generation.");
136 
137   Access = Builder.CreateGEP(Base, Indices, "polly.access." + Base->getName());
138 
139   isl_ast_expr_free(Expr);
140   return Access;
141 }
142 
143 Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) {
144   Value *LHS, *RHS, *Res;
145   Type *MaxType;
146   isl_ast_op_type OpType;
147 
148   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
149          "isl ast expression not of type isl_ast_op");
150   assert(isl_ast_expr_get_op_n_arg(Expr) == 2 &&
151          "not a binary isl ast expression");
152 
153   OpType = isl_ast_expr_get_op_type(Expr);
154 
155   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
156   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
157 
158   MaxType = LHS->getType();
159   MaxType = getWidestType(MaxType, RHS->getType());
160 
161   // Take the result into account when calculating the widest type.
162   //
163   // For operations such as '+' the result may require a type larger than
164   // the type of the individual operands. For other operations such as '/', the
165   // result type cannot be larger than the type of the individual operand. isl
166   // does not calculate correct types for these operations and we consequently
167   // exclude those operations here.
168   switch (OpType) {
169   case isl_ast_op_pdiv_q:
170   case isl_ast_op_pdiv_r:
171   case isl_ast_op_div:
172   case isl_ast_op_fdiv_q:
173     // Do nothing
174     break;
175   case isl_ast_op_add:
176   case isl_ast_op_sub:
177   case isl_ast_op_mul:
178     MaxType = getWidestType(MaxType, getType(Expr));
179     break;
180   default:
181     llvm_unreachable("This is no binary isl ast expression");
182   }
183 
184   if (MaxType != RHS->getType())
185     RHS = Builder.CreateSExt(RHS, MaxType);
186 
187   if (MaxType != LHS->getType())
188     LHS = Builder.CreateSExt(LHS, MaxType);
189 
190   switch (OpType) {
191   default:
192     llvm_unreachable("This is no binary isl ast expression");
193   case isl_ast_op_add:
194     Res = Builder.CreateNSWAdd(LHS, RHS);
195     break;
196   case isl_ast_op_sub:
197     Res = Builder.CreateNSWSub(LHS, RHS);
198     break;
199   case isl_ast_op_mul:
200     Res = Builder.CreateNSWMul(LHS, RHS);
201     break;
202   case isl_ast_op_div:
203   case isl_ast_op_pdiv_q: // Dividend is non-negative
204     Res = Builder.CreateSDiv(LHS, RHS);
205     break;
206   case isl_ast_op_fdiv_q: { // Round towards -infty
207     // TODO: Review code and check that this calculation does not yield
208     //       incorrect overflow in some bordercases.
209     //
210     // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
211     Value *One = ConstantInt::get(MaxType, 1);
212     Value *Zero = ConstantInt::get(MaxType, 0);
213     Value *Sum1 = Builder.CreateSub(LHS, RHS);
214     Value *Sum2 = Builder.CreateAdd(Sum1, One);
215     Value *isNegative = Builder.CreateICmpSLT(LHS, Zero);
216     Value *Dividend = Builder.CreateSelect(isNegative, Sum2, LHS);
217     Res = Builder.CreateSDiv(Dividend, RHS);
218     break;
219   }
220   case isl_ast_op_pdiv_r: // Dividend is non-negative
221     Res = Builder.CreateSRem(LHS, RHS);
222     break;
223   }
224 
225   // TODO: We can truncate the result, if it fits into a smaller type. This can
226   // help in cases where we have larger operands (e.g. i67) but the result is
227   // known to fit into i64. Without the truncation, the larger i67 type may
228   // force all subsequent operations to be performed on a non-native type.
229   isl_ast_expr_free(Expr);
230   return Res;
231 }
232 
233 Value *IslExprBuilder::createOpSelect(__isl_take isl_ast_expr *Expr) {
234   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_select &&
235          "Unsupported unary isl ast expression");
236   Value *LHS, *RHS, *Cond;
237   Type *MaxType = getType(Expr);
238 
239   Cond = create(isl_ast_expr_get_op_arg(Expr, 0));
240 
241   LHS = create(isl_ast_expr_get_op_arg(Expr, 1));
242   RHS = create(isl_ast_expr_get_op_arg(Expr, 2));
243 
244   MaxType = getWidestType(MaxType, LHS->getType());
245   MaxType = getWidestType(MaxType, RHS->getType());
246 
247   if (MaxType != RHS->getType())
248     RHS = Builder.CreateSExt(RHS, MaxType);
249 
250   if (MaxType != LHS->getType())
251     LHS = Builder.CreateSExt(LHS, MaxType);
252 
253   // TODO: Do we want to truncate the result?
254   isl_ast_expr_free(Expr);
255   return Builder.CreateSelect(Cond, LHS, RHS);
256 }
257 
258 Value *IslExprBuilder::createOpICmp(__isl_take isl_ast_expr *Expr) {
259   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
260          "Expected an isl_ast_expr_op expression");
261 
262   Value *LHS, *RHS, *Res;
263 
264   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
265   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
266 
267   Type *MaxType = LHS->getType();
268   MaxType = getWidestType(MaxType, RHS->getType());
269 
270   if (MaxType != RHS->getType())
271     RHS = Builder.CreateSExt(RHS, MaxType);
272 
273   if (MaxType != LHS->getType())
274     LHS = Builder.CreateSExt(LHS, MaxType);
275 
276   switch (isl_ast_expr_get_op_type(Expr)) {
277   default:
278     llvm_unreachable("Unsupported ICmp isl ast expression");
279   case isl_ast_op_eq:
280     Res = Builder.CreateICmpEQ(LHS, RHS);
281     break;
282   case isl_ast_op_le:
283     Res = Builder.CreateICmpSLE(LHS, RHS);
284     break;
285   case isl_ast_op_lt:
286     Res = Builder.CreateICmpSLT(LHS, RHS);
287     break;
288   case isl_ast_op_ge:
289     Res = Builder.CreateICmpSGE(LHS, RHS);
290     break;
291   case isl_ast_op_gt:
292     Res = Builder.CreateICmpSGT(LHS, RHS);
293     break;
294   }
295 
296   isl_ast_expr_free(Expr);
297   return Res;
298 }
299 
300 Value *IslExprBuilder::createOpBoolean(__isl_take isl_ast_expr *Expr) {
301   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
302          "Expected an isl_ast_expr_op expression");
303 
304   Value *LHS, *RHS, *Res;
305   isl_ast_op_type OpType;
306 
307   OpType = isl_ast_expr_get_op_type(Expr);
308 
309   assert((OpType == isl_ast_op_and || OpType == isl_ast_op_or) &&
310          "Unsupported isl_ast_op_type");
311 
312   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
313   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
314 
315   // Even though the isl pretty printer prints the expressions as 'exp && exp'
316   // or 'exp || exp', we actually code generate the bitwise expressions
317   // 'exp & exp' or 'exp | exp'. This forces the evaluation of both branches,
318   // but it is, due to the use of i1 types, otherwise equivalent. The reason
319   // to go for bitwise operations is, that we assume the reduced control flow
320   // will outweight the overhead introduced by evaluating unneeded expressions.
321   // The isl code generation currently does not take advantage of the fact that
322   // the expression after an '||' or '&&' is in some cases not evaluated.
323   // Evaluating it anyways does not cause any undefined behaviour.
324   //
325   // TODO: Document in isl itself, that the unconditionally evaluating the
326   // second part of '||' or '&&' expressions is safe.
327   assert(LHS->getType() == Builder.getInt1Ty() && "Expected i1 type");
328   assert(RHS->getType() == Builder.getInt1Ty() && "Expected i1 type");
329 
330   switch (OpType) {
331   default:
332     llvm_unreachable("Unsupported boolean expression");
333   case isl_ast_op_and:
334     Res = Builder.CreateAnd(LHS, RHS);
335     break;
336   case isl_ast_op_or:
337     Res = Builder.CreateOr(LHS, RHS);
338     break;
339   }
340 
341   isl_ast_expr_free(Expr);
342   return Res;
343 }
344 
345 Value *IslExprBuilder::createOp(__isl_take isl_ast_expr *Expr) {
346   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
347          "Expression not of type isl_ast_expr_op");
348   switch (isl_ast_expr_get_op_type(Expr)) {
349   case isl_ast_op_error:
350   case isl_ast_op_cond:
351   case isl_ast_op_and_then:
352   case isl_ast_op_or_else:
353   case isl_ast_op_call:
354   case isl_ast_op_member:
355     llvm_unreachable("Unsupported isl ast expression");
356   case isl_ast_op_access:
357     return createOpAccess(Expr);
358   case isl_ast_op_max:
359   case isl_ast_op_min:
360     return createOpNAry(Expr);
361   case isl_ast_op_add:
362   case isl_ast_op_sub:
363   case isl_ast_op_mul:
364   case isl_ast_op_div:
365   case isl_ast_op_fdiv_q: // Round towards -infty
366   case isl_ast_op_pdiv_q: // Dividend is non-negative
367   case isl_ast_op_pdiv_r: // Dividend is non-negative
368     return createOpBin(Expr);
369   case isl_ast_op_minus:
370     return createOpUnary(Expr);
371   case isl_ast_op_select:
372     return createOpSelect(Expr);
373   case isl_ast_op_and:
374   case isl_ast_op_or:
375     return createOpBoolean(Expr);
376   case isl_ast_op_eq:
377   case isl_ast_op_le:
378   case isl_ast_op_lt:
379   case isl_ast_op_ge:
380   case isl_ast_op_gt:
381     return createOpICmp(Expr);
382   }
383 
384   llvm_unreachable("Unsupported isl_ast_expr_op kind.");
385 }
386 
387 Value *IslExprBuilder::createId(__isl_take isl_ast_expr *Expr) {
388   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_id &&
389          "Expression not of type isl_ast_expr_ident");
390 
391   isl_id *Id;
392   Value *V;
393 
394   Id = isl_ast_expr_get_id(Expr);
395 
396   assert(IDToValue.count(Id) && "Identifier not found");
397 
398   V = IDToValue[Id];
399 
400   isl_id_free(Id);
401   isl_ast_expr_free(Expr);
402 
403   return V;
404 }
405 
406 IntegerType *IslExprBuilder::getType(__isl_keep isl_ast_expr *Expr) {
407   // XXX: We assume i64 is large enough. This is often true, but in general
408   //      incorrect. Also, on 32bit architectures, it would be beneficial to
409   //      use a smaller type. We can and should directly derive this information
410   //      during code generation.
411   return IntegerType::get(Builder.getContext(), 64);
412 }
413 
414 Value *IslExprBuilder::createInt(__isl_take isl_ast_expr *Expr) {
415   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_int &&
416          "Expression not of type isl_ast_expr_int");
417   isl_val *Val;
418   Value *V;
419   APInt APValue;
420   IntegerType *T;
421 
422   Val = isl_ast_expr_get_val(Expr);
423   APValue = APIntFromVal(Val);
424   T = getType(Expr);
425   APValue = APValue.sextOrSelf(T->getBitWidth());
426   V = ConstantInt::get(T, APValue);
427 
428   isl_ast_expr_free(Expr);
429   return V;
430 }
431 
432 Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) {
433   switch (isl_ast_expr_get_type(Expr)) {
434   case isl_ast_expr_error:
435     llvm_unreachable("Code generation error");
436   case isl_ast_expr_op:
437     return createOp(Expr);
438   case isl_ast_expr_id:
439     return createId(Expr);
440   case isl_ast_expr_int:
441     return createInt(Expr);
442   }
443 
444   llvm_unreachable("Unexpected enum value");
445 }
446