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