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