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