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/ScopInfo.h"
15 #include "polly/Support/GICHelper.h"
16 
17 #include "llvm/Analysis/ScalarEvolutionExpander.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
20 
21 using namespace llvm;
22 using namespace polly;
23 
24 Type *IslExprBuilder::getWidestType(Type *T1, Type *T2) {
25   assert(isa<IntegerType>(T1) && isa<IntegerType>(T2));
26 
27   if (T1->getPrimitiveSizeInBits() < T2->getPrimitiveSizeInBits())
28     return T2;
29   else
30     return T1;
31 }
32 
33 Value *IslExprBuilder::createOpUnary(__isl_take isl_ast_expr *Expr) {
34   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_minus &&
35          "Unsupported unary operation");
36 
37   Value *V;
38   Type *MaxType = getType(Expr);
39   assert(MaxType->isIntegerTy() &&
40          "Unary expressions can only be created for integer types");
41 
42   V = create(isl_ast_expr_get_op_arg(Expr, 0));
43   MaxType = getWidestType(MaxType, V->getType());
44 
45   if (MaxType != V->getType())
46     V = Builder.CreateSExt(V, MaxType);
47 
48   isl_ast_expr_free(Expr);
49   return Builder.CreateNSWNeg(V);
50 }
51 
52 Value *IslExprBuilder::createOpNAry(__isl_take isl_ast_expr *Expr) {
53   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
54          "isl ast expression not of type isl_ast_op");
55   assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
56          "We need at least two operands in an n-ary operation");
57 
58   Value *V;
59 
60   V = create(isl_ast_expr_get_op_arg(Expr, 0));
61 
62   for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr); ++i) {
63     Value *OpV;
64     OpV = create(isl_ast_expr_get_op_arg(Expr, i));
65 
66     Type *Ty = getWidestType(V->getType(), OpV->getType());
67 
68     if (Ty != OpV->getType())
69       OpV = Builder.CreateSExt(OpV, Ty);
70 
71     if (Ty != V->getType())
72       V = Builder.CreateSExt(V, Ty);
73 
74     switch (isl_ast_expr_get_op_type(Expr)) {
75     default:
76       llvm_unreachable("This is no n-ary isl ast expression");
77 
78     case isl_ast_op_max: {
79       Value *Cmp = Builder.CreateICmpSGT(V, OpV);
80       V = Builder.CreateSelect(Cmp, V, OpV);
81       continue;
82     }
83     case isl_ast_op_min: {
84       Value *Cmp = Builder.CreateICmpSLT(V, OpV);
85       V = Builder.CreateSelect(Cmp, V, OpV);
86       continue;
87     }
88     }
89   }
90 
91   // TODO: We can truncate the result, if it fits into a smaller type. This can
92   // help in cases where we have larger operands (e.g. i67) but the result is
93   // known to fit into i64. Without the truncation, the larger i67 type may
94   // force all subsequent operations to be performed on a non-native type.
95   isl_ast_expr_free(Expr);
96   return V;
97 }
98 
99 Value *IslExprBuilder::createAccessAddress(isl_ast_expr *Expr) {
100   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
101          "isl ast expression not of type isl_ast_op");
102   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_access &&
103          "not an access isl ast expression");
104   assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 &&
105          "We need at least two operands to create a member access.");
106 
107   Value *Base, *IndexOp, *Access;
108   isl_ast_expr *BaseExpr;
109   isl_id *BaseId;
110 
111   BaseExpr = isl_ast_expr_get_op_arg(Expr, 0);
112   BaseId = isl_ast_expr_get_id(BaseExpr);
113   isl_ast_expr_free(BaseExpr);
114 
115   const ScopArrayInfo *SAI = ScopArrayInfo::getFromId(BaseId);
116   Base = SAI->getBasePtr();
117   assert(Base->getType()->isPointerTy() && "Access base should be a pointer");
118   StringRef BaseName = Base->getName();
119 
120   if (Base->getType() != SAI->getType())
121     Base = Builder.CreateBitCast(Base, SAI->getType(),
122                                  "polly.access.cast." + BaseName);
123 
124   IndexOp = nullptr;
125   for (unsigned u = 1, e = isl_ast_expr_get_op_n_arg(Expr); u < e; u++) {
126     Value *NextIndex = create(isl_ast_expr_get_op_arg(Expr, u));
127     assert(NextIndex->getType()->isIntegerTy() &&
128            "Access index should be an integer");
129 
130     if (!IndexOp)
131       IndexOp = NextIndex;
132     else
133       IndexOp =
134           Builder.CreateAdd(IndexOp, NextIndex, "polly.access.add." + BaseName);
135 
136     // For every but the last dimension multiply the size, for the last
137     // dimension we can exit the loop.
138     if (u + 1 >= e)
139       break;
140 
141     const SCEV *DimSCEV = SAI->getDimensionSize(u - 1);
142     Value *DimSize = Expander.expandCodeFor(DimSCEV, DimSCEV->getType(),
143                                             Builder.GetInsertPoint());
144 
145     Type *Ty = getWidestType(DimSize->getType(), IndexOp->getType());
146 
147     if (Ty != IndexOp->getType())
148       IndexOp = Builder.CreateSExtOrTrunc(IndexOp, Ty,
149                                           "polly.access.sext." + BaseName);
150 
151     IndexOp =
152         Builder.CreateMul(IndexOp, DimSize, "polly.access.mul." + BaseName);
153   }
154 
155   Access = Builder.CreateGEP(Base, IndexOp, "polly.access." + BaseName);
156 
157   isl_ast_expr_free(Expr);
158   return Access;
159 }
160 
161 Value *IslExprBuilder::createOpAccess(isl_ast_expr *Expr) {
162   Value *Addr = createAccessAddress(Expr);
163   assert(Addr && "Could not create op access address");
164   return Builder.CreateLoad(Addr, Addr->getName() + ".load");
165 }
166 
167 Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) {
168   Value *LHS, *RHS, *Res;
169   Type *MaxType;
170   isl_ast_expr *LOp, *ROp;
171   isl_ast_op_type OpType;
172 
173   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
174          "isl ast expression not of type isl_ast_op");
175   assert(isl_ast_expr_get_op_n_arg(Expr) == 2 &&
176          "not a binary isl ast expression");
177 
178   OpType = isl_ast_expr_get_op_type(Expr);
179 
180   LOp = isl_ast_expr_get_op_arg(Expr, 0);
181   ROp = isl_ast_expr_get_op_arg(Expr, 1);
182 
183   // Catch the special case ((-<pointer>) + <pointer>) which is for
184   // isl the same as (<pointer> - <pointer>). We have to treat it here because
185   // there is no valid semantics for the (-<pointer>) expression, hence in
186   // createOpUnary such an expression will trigger a crash.
187   // FIXME: The same problem can now be triggered by a subexpression of the LHS,
188   //        however it is much less likely.
189   if (OpType == isl_ast_op_add &&
190       isl_ast_expr_get_type(LOp) == isl_ast_expr_op &&
191       isl_ast_expr_get_op_type(LOp) == isl_ast_op_minus) {
192     // Change the binary addition to a substraction.
193     OpType = isl_ast_op_sub;
194 
195     // Extract the unary operand of the LHS.
196     auto *LOpOp = isl_ast_expr_get_op_arg(LOp, 0);
197     isl_ast_expr_free(LOp);
198 
199     // Swap the unary operand of the LHS and the RHS.
200     LOp = ROp;
201     ROp = LOpOp;
202   }
203 
204   LHS = create(LOp);
205   RHS = create(ROp);
206 
207   Type *LHSType = LHS->getType();
208   Type *RHSType = RHS->getType();
209 
210   // Handle <pointer> - <pointer>
211   if (LHSType->isPointerTy() && RHSType->isPointerTy()) {
212     isl_ast_expr_free(Expr);
213     assert(OpType == isl_ast_op_sub && "Substraction is the only valid binary "
214                                        "pointer <-> pointer operation.");
215 
216     return Builder.CreatePtrDiff(LHS, RHS);
217   }
218 
219   // Handle <pointer> +/- <integer> and <integer> +/- <pointer>
220   if (LHSType->isPointerTy() || RHSType->isPointerTy()) {
221     isl_ast_expr_free(Expr);
222 
223     assert((LHSType->isIntegerTy() || RHSType->isIntegerTy()) &&
224            "Arithmetic operations might only performed on one but not two "
225            "pointer types.");
226 
227     if (LHSType->isIntegerTy())
228       std::swap(LHS, RHS);
229 
230     switch (OpType) {
231     default:
232       llvm_unreachable(
233           "Only additive binary operations are allowed on pointer types.");
234     case isl_ast_op_sub:
235       RHS = Builder.CreateNeg(RHS);
236     // Fall through
237     case isl_ast_op_add:
238       return Builder.CreateGEP(LHS, RHS);
239     }
240   }
241 
242   MaxType = getWidestType(LHSType, RHSType);
243 
244   // Take the result into account when calculating the widest type.
245   //
246   // For operations such as '+' the result may require a type larger than
247   // the type of the individual operands. For other operations such as '/', the
248   // result type cannot be larger than the type of the individual operand. isl
249   // does not calculate correct types for these operations and we consequently
250   // exclude those operations here.
251   switch (OpType) {
252   case isl_ast_op_pdiv_q:
253   case isl_ast_op_pdiv_r:
254   case isl_ast_op_div:
255   case isl_ast_op_fdiv_q:
256   case isl_ast_op_zdiv_r:
257     // Do nothing
258     break;
259   case isl_ast_op_add:
260   case isl_ast_op_sub:
261   case isl_ast_op_mul:
262     MaxType = getWidestType(MaxType, getType(Expr));
263     break;
264   default:
265     llvm_unreachable("This is no binary isl ast expression");
266   }
267 
268   if (MaxType != RHS->getType())
269     RHS = Builder.CreateSExt(RHS, MaxType);
270 
271   if (MaxType != LHS->getType())
272     LHS = Builder.CreateSExt(LHS, MaxType);
273 
274   switch (OpType) {
275   default:
276     llvm_unreachable("This is no binary isl ast expression");
277   case isl_ast_op_add:
278     Res = Builder.CreateNSWAdd(LHS, RHS);
279     break;
280   case isl_ast_op_sub:
281     Res = Builder.CreateNSWSub(LHS, RHS);
282     break;
283   case isl_ast_op_mul:
284     Res = Builder.CreateNSWMul(LHS, RHS);
285     break;
286   case isl_ast_op_div:
287   case isl_ast_op_pdiv_q: // Dividend is non-negative
288     Res = Builder.CreateSDiv(LHS, RHS);
289     break;
290   case isl_ast_op_fdiv_q: { // Round towards -infty
291     // TODO: Review code and check that this calculation does not yield
292     //       incorrect overflow in some bordercases.
293     //
294     // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d
295     Value *One = ConstantInt::get(MaxType, 1);
296     Value *Zero = ConstantInt::get(MaxType, 0);
297     Value *Sum1 = Builder.CreateSub(LHS, RHS);
298     Value *Sum2 = Builder.CreateAdd(Sum1, One);
299     Value *isNegative = Builder.CreateICmpSLT(LHS, Zero);
300     Value *Dividend = Builder.CreateSelect(isNegative, Sum2, LHS);
301     Res = Builder.CreateSDiv(Dividend, RHS);
302     break;
303   }
304   case isl_ast_op_pdiv_r: // Dividend is non-negative
305   case isl_ast_op_zdiv_r: // Result only compared against zero
306     Res = Builder.CreateSRem(LHS, RHS);
307     break;
308   }
309 
310   // TODO: We can truncate the result, if it fits into a smaller type. This can
311   // help in cases where we have larger operands (e.g. i67) but the result is
312   // known to fit into i64. Without the truncation, the larger i67 type may
313   // force all subsequent operations to be performed on a non-native type.
314   isl_ast_expr_free(Expr);
315   return Res;
316 }
317 
318 Value *IslExprBuilder::createOpSelect(__isl_take isl_ast_expr *Expr) {
319   assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_select &&
320          "Unsupported unary isl ast expression");
321   Value *LHS, *RHS, *Cond;
322   Type *MaxType = getType(Expr);
323 
324   Cond = create(isl_ast_expr_get_op_arg(Expr, 0));
325   if (!Cond->getType()->isIntegerTy(1))
326     Cond = Builder.CreateIsNotNull(Cond);
327 
328   LHS = create(isl_ast_expr_get_op_arg(Expr, 1));
329   RHS = create(isl_ast_expr_get_op_arg(Expr, 2));
330 
331   MaxType = getWidestType(MaxType, LHS->getType());
332   MaxType = getWidestType(MaxType, RHS->getType());
333 
334   if (MaxType != RHS->getType())
335     RHS = Builder.CreateSExt(RHS, MaxType);
336 
337   if (MaxType != LHS->getType())
338     LHS = Builder.CreateSExt(LHS, MaxType);
339 
340   // TODO: Do we want to truncate the result?
341   isl_ast_expr_free(Expr);
342   return Builder.CreateSelect(Cond, LHS, RHS);
343 }
344 
345 Value *IslExprBuilder::createOpICmp(__isl_take isl_ast_expr *Expr) {
346   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
347          "Expected an isl_ast_expr_op expression");
348 
349   Value *LHS, *RHS, *Res;
350 
351   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
352   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
353 
354   bool IsPtrType =
355       LHS->getType()->isPointerTy() || RHS->getType()->isPointerTy();
356 
357   if (LHS->getType() != RHS->getType()) {
358     if (IsPtrType) {
359       Type *I8PtrTy = Builder.getInt8PtrTy();
360       if (!LHS->getType()->isPointerTy())
361         LHS = Builder.CreateIntToPtr(LHS, I8PtrTy);
362       if (!RHS->getType()->isPointerTy())
363         RHS = Builder.CreateIntToPtr(RHS, I8PtrTy);
364       if (LHS->getType() != I8PtrTy)
365         LHS = Builder.CreateBitCast(LHS, I8PtrTy);
366       if (RHS->getType() != I8PtrTy)
367         RHS = Builder.CreateBitCast(RHS, I8PtrTy);
368     } else {
369       Type *MaxType = LHS->getType();
370       MaxType = getWidestType(MaxType, RHS->getType());
371 
372       if (MaxType != RHS->getType())
373         RHS = Builder.CreateSExt(RHS, MaxType);
374 
375       if (MaxType != LHS->getType())
376         LHS = Builder.CreateSExt(LHS, MaxType);
377     }
378   }
379 
380   isl_ast_op_type OpType = isl_ast_expr_get_op_type(Expr);
381   assert(OpType >= isl_ast_op_eq && OpType <= isl_ast_op_gt &&
382          "Unsupported ICmp isl ast expression");
383   assert(isl_ast_op_eq + 4 == isl_ast_op_gt &&
384          "Isl ast op type interface changed");
385 
386   CmpInst::Predicate Predicates[5][2] = {
387       {CmpInst::ICMP_EQ, CmpInst::ICMP_EQ},
388       {CmpInst::ICMP_SLE, CmpInst::ICMP_ULE},
389       {CmpInst::ICMP_SLT, CmpInst::ICMP_ULT},
390       {CmpInst::ICMP_SGE, CmpInst::ICMP_UGE},
391       {CmpInst::ICMP_SGT, CmpInst::ICMP_UGT},
392   };
393 
394   Res = Builder.CreateICmp(Predicates[OpType - isl_ast_op_eq][IsPtrType], LHS,
395                            RHS);
396 
397   isl_ast_expr_free(Expr);
398   return Res;
399 }
400 
401 Value *IslExprBuilder::createOpBoolean(__isl_take isl_ast_expr *Expr) {
402   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
403          "Expected an isl_ast_expr_op expression");
404 
405   Value *LHS, *RHS, *Res;
406   isl_ast_op_type OpType;
407 
408   OpType = isl_ast_expr_get_op_type(Expr);
409 
410   assert((OpType == isl_ast_op_and || OpType == isl_ast_op_or) &&
411          "Unsupported isl_ast_op_type");
412 
413   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
414   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
415 
416   // Even though the isl pretty printer prints the expressions as 'exp && exp'
417   // or 'exp || exp', we actually code generate the bitwise expressions
418   // 'exp & exp' or 'exp | exp'. This forces the evaluation of both branches,
419   // but it is, due to the use of i1 types, otherwise equivalent. The reason
420   // to go for bitwise operations is, that we assume the reduced control flow
421   // will outweight the overhead introduced by evaluating unneeded expressions.
422   // The isl code generation currently does not take advantage of the fact that
423   // the expression after an '||' or '&&' is in some cases not evaluated.
424   // Evaluating it anyways does not cause any undefined behaviour.
425   //
426   // TODO: Document in isl itself, that the unconditionally evaluating the
427   // second part of '||' or '&&' expressions is safe.
428   if (!LHS->getType()->isIntegerTy(1))
429     LHS = Builder.CreateIsNotNull(LHS);
430   if (!RHS->getType()->isIntegerTy(1))
431     RHS = Builder.CreateIsNotNull(RHS);
432 
433   switch (OpType) {
434   default:
435     llvm_unreachable("Unsupported boolean expression");
436   case isl_ast_op_and:
437     Res = Builder.CreateAnd(LHS, RHS);
438     break;
439   case isl_ast_op_or:
440     Res = Builder.CreateOr(LHS, RHS);
441     break;
442   }
443 
444   isl_ast_expr_free(Expr);
445   return Res;
446 }
447 
448 Value *
449 IslExprBuilder::createOpBooleanConditional(__isl_take isl_ast_expr *Expr) {
450   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
451          "Expected an isl_ast_expr_op expression");
452 
453   Value *LHS, *RHS;
454   isl_ast_op_type OpType;
455 
456   Function *F = Builder.GetInsertBlock()->getParent();
457   LLVMContext &Context = F->getContext();
458 
459   OpType = isl_ast_expr_get_op_type(Expr);
460 
461   assert((OpType == isl_ast_op_and_then || OpType == isl_ast_op_or_else) &&
462          "Unsupported isl_ast_op_type");
463 
464   auto InsertBB = Builder.GetInsertBlock();
465   auto InsertPoint = Builder.GetInsertPoint();
466   auto NextBB = SplitBlock(InsertBB, InsertPoint, &DT, &LI);
467   BasicBlock *CondBB = BasicBlock::Create(Context, "polly.cond", F);
468   LI.changeLoopFor(CondBB, LI.getLoopFor(InsertBB));
469   DT.addNewBlock(CondBB, InsertBB);
470 
471   InsertBB->getTerminator()->eraseFromParent();
472   Builder.SetInsertPoint(InsertBB);
473   auto BR = Builder.CreateCondBr(Builder.getTrue(), NextBB, CondBB);
474 
475   Builder.SetInsertPoint(CondBB);
476   Builder.CreateBr(NextBB);
477 
478   Builder.SetInsertPoint(InsertBB->getTerminator());
479 
480   LHS = create(isl_ast_expr_get_op_arg(Expr, 0));
481   if (!LHS->getType()->isIntegerTy(1))
482     LHS = Builder.CreateIsNotNull(LHS);
483   auto LeftBB = Builder.GetInsertBlock();
484 
485   if (OpType == isl_ast_op_and || OpType == isl_ast_op_and_then)
486     BR->setCondition(Builder.CreateNeg(LHS));
487   else
488     BR->setCondition(LHS);
489 
490   Builder.SetInsertPoint(CondBB->getTerminator());
491   RHS = create(isl_ast_expr_get_op_arg(Expr, 1));
492   if (!RHS->getType()->isIntegerTy(1))
493     RHS = Builder.CreateIsNotNull(RHS);
494   auto RightBB = Builder.GetInsertBlock();
495 
496   Builder.SetInsertPoint(NextBB->getTerminator());
497   auto PHI = Builder.CreatePHI(Builder.getInt1Ty(), 2);
498   PHI->addIncoming(OpType == isl_ast_op_and_then ? Builder.getFalse()
499                                                  : Builder.getTrue(),
500                    LeftBB);
501   PHI->addIncoming(RHS, RightBB);
502 
503   isl_ast_expr_free(Expr);
504   return PHI;
505 }
506 
507 Value *IslExprBuilder::createOp(__isl_take isl_ast_expr *Expr) {
508   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
509          "Expression not of type isl_ast_expr_op");
510   switch (isl_ast_expr_get_op_type(Expr)) {
511   case isl_ast_op_error:
512   case isl_ast_op_cond:
513   case isl_ast_op_call:
514   case isl_ast_op_member:
515     llvm_unreachable("Unsupported isl ast expression");
516   case isl_ast_op_access:
517     return createOpAccess(Expr);
518   case isl_ast_op_max:
519   case isl_ast_op_min:
520     return createOpNAry(Expr);
521   case isl_ast_op_add:
522   case isl_ast_op_sub:
523   case isl_ast_op_mul:
524   case isl_ast_op_div:
525   case isl_ast_op_fdiv_q: // Round towards -infty
526   case isl_ast_op_pdiv_q: // Dividend is non-negative
527   case isl_ast_op_pdiv_r: // Dividend is non-negative
528   case isl_ast_op_zdiv_r: // Result only compared against zero
529     return createOpBin(Expr);
530   case isl_ast_op_minus:
531     return createOpUnary(Expr);
532   case isl_ast_op_select:
533     return createOpSelect(Expr);
534   case isl_ast_op_and:
535   case isl_ast_op_or:
536     return createOpBoolean(Expr);
537   case isl_ast_op_and_then:
538   case isl_ast_op_or_else:
539     return createOpBooleanConditional(Expr);
540   case isl_ast_op_eq:
541   case isl_ast_op_le:
542   case isl_ast_op_lt:
543   case isl_ast_op_ge:
544   case isl_ast_op_gt:
545     return createOpICmp(Expr);
546   case isl_ast_op_address_of:
547     return createOpAddressOf(Expr);
548   }
549 
550   llvm_unreachable("Unsupported isl_ast_expr_op kind.");
551 }
552 
553 Value *IslExprBuilder::createOpAddressOf(__isl_take isl_ast_expr *Expr) {
554   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op &&
555          "Expected an isl_ast_expr_op expression.");
556   assert(isl_ast_expr_get_op_n_arg(Expr) == 1 && "Address of should be unary.");
557 
558   isl_ast_expr *Op = isl_ast_expr_get_op_arg(Expr, 0);
559   assert(isl_ast_expr_get_type(Op) == isl_ast_expr_op &&
560          "Expected address of operator to be an isl_ast_expr_op expression.");
561   assert(isl_ast_expr_get_op_type(Op) == isl_ast_op_access &&
562          "Expected address of operator to be an access expression.");
563 
564   Value *V = createAccessAddress(Op);
565 
566   isl_ast_expr_free(Expr);
567 
568   return V;
569 }
570 
571 Value *IslExprBuilder::createId(__isl_take isl_ast_expr *Expr) {
572   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_id &&
573          "Expression not of type isl_ast_expr_ident");
574 
575   isl_id *Id;
576   Value *V;
577 
578   Id = isl_ast_expr_get_id(Expr);
579 
580   assert(IDToValue.count(Id) && "Identifier not found");
581 
582   V = IDToValue[Id];
583 
584   isl_id_free(Id);
585   isl_ast_expr_free(Expr);
586 
587   return V;
588 }
589 
590 IntegerType *IslExprBuilder::getType(__isl_keep isl_ast_expr *Expr) {
591   // XXX: We assume i64 is large enough. This is often true, but in general
592   //      incorrect. Also, on 32bit architectures, it would be beneficial to
593   //      use a smaller type. We can and should directly derive this information
594   //      during code generation.
595   return IntegerType::get(Builder.getContext(), 64);
596 }
597 
598 Value *IslExprBuilder::createInt(__isl_take isl_ast_expr *Expr) {
599   assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_int &&
600          "Expression not of type isl_ast_expr_int");
601   isl_val *Val;
602   Value *V;
603   APInt APValue;
604   IntegerType *T;
605 
606   Val = isl_ast_expr_get_val(Expr);
607   APValue = APIntFromVal(Val);
608   T = getType(Expr);
609   APValue = APValue.sextOrSelf(T->getBitWidth());
610   V = ConstantInt::get(T, APValue);
611 
612   isl_ast_expr_free(Expr);
613   return V;
614 }
615 
616 Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) {
617   switch (isl_ast_expr_get_type(Expr)) {
618   case isl_ast_expr_error:
619     llvm_unreachable("Code generation error");
620   case isl_ast_expr_op:
621     return createOp(Expr);
622   case isl_ast_expr_id:
623     return createId(Expr);
624   case isl_ast_expr_int:
625     return createInt(Expr);
626   }
627 
628   llvm_unreachable("Unexpected enum value");
629 }
630