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 116 if (auto NewBase = GlobalMap.lookup(Base)) 117 Base = NewBase; 118 119 assert(Base->getType()->isPointerTy() && "Access base should be a pointer"); 120 StringRef BaseName = Base->getName(); 121 122 auto PointerTy = PointerType::get(SAI->getElementType(), 123 Base->getType()->getPointerAddressSpace()); 124 if (Base->getType() != PointerTy) { 125 Base = 126 Builder.CreateBitCast(Base, PointerTy, "polly.access.cast." + BaseName); 127 } 128 129 IndexOp = nullptr; 130 for (unsigned u = 1, e = isl_ast_expr_get_op_n_arg(Expr); u < e; u++) { 131 Value *NextIndex = create(isl_ast_expr_get_op_arg(Expr, u)); 132 assert(NextIndex->getType()->isIntegerTy() && 133 "Access index should be an integer"); 134 135 if (!IndexOp) { 136 IndexOp = NextIndex; 137 } else { 138 Type *Ty = getWidestType(NextIndex->getType(), IndexOp->getType()); 139 140 if (Ty != NextIndex->getType()) 141 NextIndex = Builder.CreateIntCast(NextIndex, Ty, true); 142 if (Ty != IndexOp->getType()) 143 IndexOp = Builder.CreateIntCast(IndexOp, Ty, true); 144 145 IndexOp = 146 Builder.CreateAdd(IndexOp, NextIndex, "polly.access.add." + BaseName); 147 } 148 149 // For every but the last dimension multiply the size, for the last 150 // dimension we can exit the loop. 151 if (u + 1 >= e) 152 break; 153 154 const SCEV *DimSCEV = SAI->getDimensionSize(u - 1); 155 156 DimSCEV = SCEVParameterRewriter::rewrite(DimSCEV, SE, GlobalMap); 157 Value *DimSize = 158 expandCodeFor(S, SE, DL, "polly", DimSCEV, DimSCEV->getType(), 159 Builder.GetInsertPoint()); 160 161 Type *Ty = getWidestType(DimSize->getType(), IndexOp->getType()); 162 163 if (Ty != IndexOp->getType()) 164 IndexOp = Builder.CreateSExtOrTrunc(IndexOp, Ty, 165 "polly.access.sext." + BaseName); 166 if (Ty != DimSize->getType()) 167 DimSize = Builder.CreateSExtOrTrunc(DimSize, Ty, 168 "polly.access.sext." + BaseName); 169 IndexOp = 170 Builder.CreateMul(IndexOp, DimSize, "polly.access.mul." + BaseName); 171 } 172 173 Access = Builder.CreateGEP(Base, IndexOp, "polly.access." + BaseName); 174 175 isl_ast_expr_free(Expr); 176 return Access; 177 } 178 179 Value *IslExprBuilder::createOpAccess(isl_ast_expr *Expr) { 180 Value *Addr = createAccessAddress(Expr); 181 assert(Addr && "Could not create op access address"); 182 return Builder.CreateLoad(Addr, Addr->getName() + ".load"); 183 } 184 185 Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) { 186 Value *LHS, *RHS, *Res; 187 Type *MaxType; 188 isl_ast_expr *LOp, *ROp; 189 isl_ast_op_type OpType; 190 191 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 192 "isl ast expression not of type isl_ast_op"); 193 assert(isl_ast_expr_get_op_n_arg(Expr) == 2 && 194 "not a binary isl ast expression"); 195 196 OpType = isl_ast_expr_get_op_type(Expr); 197 198 LOp = isl_ast_expr_get_op_arg(Expr, 0); 199 ROp = isl_ast_expr_get_op_arg(Expr, 1); 200 201 // Catch the special case ((-<pointer>) + <pointer>) which is for 202 // isl the same as (<pointer> - <pointer>). We have to treat it here because 203 // there is no valid semantics for the (-<pointer>) expression, hence in 204 // createOpUnary such an expression will trigger a crash. 205 // FIXME: The same problem can now be triggered by a subexpression of the LHS, 206 // however it is much less likely. 207 if (OpType == isl_ast_op_add && 208 isl_ast_expr_get_type(LOp) == isl_ast_expr_op && 209 isl_ast_expr_get_op_type(LOp) == isl_ast_op_minus) { 210 // Change the binary addition to a substraction. 211 OpType = isl_ast_op_sub; 212 213 // Extract the unary operand of the LHS. 214 auto *LOpOp = isl_ast_expr_get_op_arg(LOp, 0); 215 isl_ast_expr_free(LOp); 216 217 // Swap the unary operand of the LHS and the RHS. 218 LOp = ROp; 219 ROp = LOpOp; 220 } 221 222 LHS = create(LOp); 223 RHS = create(ROp); 224 225 Type *LHSType = LHS->getType(); 226 Type *RHSType = RHS->getType(); 227 228 // Handle <pointer> - <pointer> 229 if (LHSType->isPointerTy() && RHSType->isPointerTy()) { 230 isl_ast_expr_free(Expr); 231 assert(OpType == isl_ast_op_sub && "Substraction is the only valid binary " 232 "pointer <-> pointer operation."); 233 234 return Builder.CreatePtrDiff(LHS, RHS); 235 } 236 237 // Handle <pointer> +/- <integer> and <integer> +/- <pointer> 238 if (LHSType->isPointerTy() || RHSType->isPointerTy()) { 239 isl_ast_expr_free(Expr); 240 241 assert((LHSType->isIntegerTy() || RHSType->isIntegerTy()) && 242 "Arithmetic operations might only performed on one but not two " 243 "pointer types."); 244 245 if (LHSType->isIntegerTy()) 246 std::swap(LHS, RHS); 247 248 switch (OpType) { 249 default: 250 llvm_unreachable( 251 "Only additive binary operations are allowed on pointer types."); 252 case isl_ast_op_sub: 253 RHS = Builder.CreateNeg(RHS); 254 // Fall through 255 case isl_ast_op_add: 256 return Builder.CreateGEP(LHS, RHS); 257 } 258 } 259 260 MaxType = getWidestType(LHSType, RHSType); 261 262 // Take the result into account when calculating the widest type. 263 // 264 // For operations such as '+' the result may require a type larger than 265 // the type of the individual operands. For other operations such as '/', the 266 // result type cannot be larger than the type of the individual operand. isl 267 // does not calculate correct types for these operations and we consequently 268 // exclude those operations here. 269 switch (OpType) { 270 case isl_ast_op_pdiv_q: 271 case isl_ast_op_pdiv_r: 272 case isl_ast_op_div: 273 case isl_ast_op_fdiv_q: 274 case isl_ast_op_zdiv_r: 275 // Do nothing 276 break; 277 case isl_ast_op_add: 278 case isl_ast_op_sub: 279 case isl_ast_op_mul: 280 MaxType = getWidestType(MaxType, getType(Expr)); 281 break; 282 default: 283 llvm_unreachable("This is no binary isl ast expression"); 284 } 285 286 if (MaxType != RHS->getType()) 287 RHS = Builder.CreateSExt(RHS, MaxType); 288 289 if (MaxType != LHS->getType()) 290 LHS = Builder.CreateSExt(LHS, MaxType); 291 292 switch (OpType) { 293 default: 294 llvm_unreachable("This is no binary isl ast expression"); 295 case isl_ast_op_add: 296 Res = Builder.CreateNSWAdd(LHS, RHS); 297 break; 298 case isl_ast_op_sub: 299 Res = Builder.CreateNSWSub(LHS, RHS); 300 break; 301 case isl_ast_op_mul: 302 Res = Builder.CreateNSWMul(LHS, RHS); 303 break; 304 case isl_ast_op_div: 305 Res = Builder.CreateSDiv(LHS, RHS, "pexp.div", true); 306 break; 307 case isl_ast_op_pdiv_q: // Dividend is non-negative 308 Res = Builder.CreateUDiv(LHS, RHS, "pexp.p_div_q"); 309 break; 310 case isl_ast_op_fdiv_q: { // Round towards -infty 311 if (auto *Const = dyn_cast<ConstantInt>(RHS)) { 312 auto &Val = Const->getValue(); 313 if (Val.isPowerOf2() && Val.isNonNegative()) { 314 Res = Builder.CreateAShr(LHS, Val.ceilLogBase2(), "polly.fdiv_q.shr"); 315 break; 316 } 317 } 318 // TODO: Review code and check that this calculation does not yield 319 // incorrect overflow in some bordercases. 320 // 321 // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d 322 Value *One = ConstantInt::get(MaxType, 1); 323 Value *Zero = ConstantInt::get(MaxType, 0); 324 Value *Sum1 = Builder.CreateSub(LHS, RHS, "pexp.fdiv_q.0"); 325 Value *Sum2 = Builder.CreateAdd(Sum1, One, "pexp.fdiv_q.1"); 326 Value *isNegative = Builder.CreateICmpSLT(LHS, Zero, "pexp.fdiv_q.2"); 327 Value *Dividend = 328 Builder.CreateSelect(isNegative, Sum2, LHS, "pexp.fdiv_q.3"); 329 Res = Builder.CreateSDiv(Dividend, RHS, "pexp.fdiv_q.4"); 330 break; 331 } 332 case isl_ast_op_pdiv_r: // Dividend is non-negative 333 Res = Builder.CreateURem(LHS, RHS, "pexp.pdiv_r"); 334 break; 335 336 case isl_ast_op_zdiv_r: // Result only compared against zero 337 Res = Builder.CreateURem(LHS, RHS, "pexp.zdiv_r"); 338 break; 339 } 340 341 // TODO: We can truncate the result, if it fits into a smaller type. This can 342 // help in cases where we have larger operands (e.g. i67) but the result is 343 // known to fit into i64. Without the truncation, the larger i67 type may 344 // force all subsequent operations to be performed on a non-native type. 345 isl_ast_expr_free(Expr); 346 return Res; 347 } 348 349 Value *IslExprBuilder::createOpSelect(__isl_take isl_ast_expr *Expr) { 350 assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_select && 351 "Unsupported unary isl ast expression"); 352 Value *LHS, *RHS, *Cond; 353 Type *MaxType = getType(Expr); 354 355 Cond = create(isl_ast_expr_get_op_arg(Expr, 0)); 356 if (!Cond->getType()->isIntegerTy(1)) 357 Cond = Builder.CreateIsNotNull(Cond); 358 359 LHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 360 RHS = create(isl_ast_expr_get_op_arg(Expr, 2)); 361 362 MaxType = getWidestType(MaxType, LHS->getType()); 363 MaxType = getWidestType(MaxType, RHS->getType()); 364 365 if (MaxType != RHS->getType()) 366 RHS = Builder.CreateSExt(RHS, MaxType); 367 368 if (MaxType != LHS->getType()) 369 LHS = Builder.CreateSExt(LHS, MaxType); 370 371 // TODO: Do we want to truncate the result? 372 isl_ast_expr_free(Expr); 373 return Builder.CreateSelect(Cond, LHS, RHS); 374 } 375 376 Value *IslExprBuilder::createOpICmp(__isl_take isl_ast_expr *Expr) { 377 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 378 "Expected an isl_ast_expr_op expression"); 379 380 Value *LHS, *RHS, *Res; 381 382 LHS = create(isl_ast_expr_get_op_arg(Expr, 0)); 383 RHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 384 385 bool IsPtrType = 386 LHS->getType()->isPointerTy() || RHS->getType()->isPointerTy(); 387 388 if (LHS->getType() != RHS->getType()) { 389 if (IsPtrType) { 390 Type *I8PtrTy = Builder.getInt8PtrTy(); 391 if (!LHS->getType()->isPointerTy()) 392 LHS = Builder.CreateIntToPtr(LHS, I8PtrTy); 393 if (!RHS->getType()->isPointerTy()) 394 RHS = Builder.CreateIntToPtr(RHS, I8PtrTy); 395 if (LHS->getType() != I8PtrTy) 396 LHS = Builder.CreateBitCast(LHS, I8PtrTy); 397 if (RHS->getType() != I8PtrTy) 398 RHS = Builder.CreateBitCast(RHS, I8PtrTy); 399 } else { 400 Type *MaxType = LHS->getType(); 401 MaxType = getWidestType(MaxType, RHS->getType()); 402 403 if (MaxType != RHS->getType()) 404 RHS = Builder.CreateSExt(RHS, MaxType); 405 406 if (MaxType != LHS->getType()) 407 LHS = Builder.CreateSExt(LHS, MaxType); 408 } 409 } 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][IsPtrType], LHS, 426 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 615 assert(V && "Unknown parameter id found"); 616 617 isl_id_free(Id); 618 isl_ast_expr_free(Expr); 619 620 return V; 621 } 622 623 IntegerType *IslExprBuilder::getType(__isl_keep isl_ast_expr *Expr) { 624 // XXX: We assume i64 is large enough. This is often true, but in general 625 // incorrect. Also, on 32bit architectures, it would be beneficial to 626 // use a smaller type. We can and should directly derive this information 627 // during code generation. 628 return IntegerType::get(Builder.getContext(), 64); 629 } 630 631 Value *IslExprBuilder::createInt(__isl_take isl_ast_expr *Expr) { 632 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_int && 633 "Expression not of type isl_ast_expr_int"); 634 isl_val *Val; 635 Value *V; 636 APInt APValue; 637 IntegerType *T; 638 639 Val = isl_ast_expr_get_val(Expr); 640 APValue = APIntFromVal(Val); 641 T = getType(Expr); 642 APValue = APValue.sextOrSelf(T->getBitWidth()); 643 V = ConstantInt::get(T, APValue); 644 645 isl_ast_expr_free(Expr); 646 return V; 647 } 648 649 Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) { 650 switch (isl_ast_expr_get_type(Expr)) { 651 case isl_ast_expr_error: 652 llvm_unreachable("Code generation error"); 653 case isl_ast_expr_op: 654 return createOp(Expr); 655 case isl_ast_expr_id: 656 return createId(Expr); 657 case isl_ast_expr_int: 658 return createInt(Expr); 659 } 660 661 llvm_unreachable("Unexpected enum value"); 662 } 663