1 //===------ IslExprBuilder.cpp ----- Code generate isl AST expressions ----===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include "polly/CodeGen/IslExprBuilder.h" 13 14 #include "polly/Support/GICHelper.h" 15 16 #include "llvm/Support/Debug.h" 17 18 using namespace llvm; 19 using namespace polly; 20 21 Type *IslExprBuilder::getWidestType(Type *T1, Type *T2) { 22 assert(isa<IntegerType>(T1) && isa<IntegerType>(T2)); 23 24 if (T1->getPrimitiveSizeInBits() < T2->getPrimitiveSizeInBits()) 25 return T2; 26 else 27 return T1; 28 } 29 30 Value *IslExprBuilder::createOpUnary(__isl_take isl_ast_expr *Expr) { 31 assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_minus && 32 "Unsupported unary operation"); 33 34 Value *V; 35 Type *MaxType = getType(Expr); 36 37 V = create(isl_ast_expr_get_op_arg(Expr, 0)); 38 MaxType = getWidestType(MaxType, V->getType()); 39 40 if (MaxType != V->getType()) 41 V = Builder.CreateSExt(V, MaxType); 42 43 isl_ast_expr_free(Expr); 44 return Builder.CreateNSWNeg(V); 45 } 46 47 Value *IslExprBuilder::createOpNAry(__isl_take isl_ast_expr *Expr) { 48 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 49 "isl ast expression not of type isl_ast_op"); 50 assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 && 51 "We need at least two operands in an n-ary operation"); 52 53 Value *V; 54 55 V = create(isl_ast_expr_get_op_arg(Expr, 0)); 56 57 for (int i = 0; i < isl_ast_expr_get_op_n_arg(Expr); ++i) { 58 Value *OpV; 59 OpV = create(isl_ast_expr_get_op_arg(Expr, i)); 60 61 Type *Ty = getWidestType(V->getType(), OpV->getType()); 62 63 if (Ty != OpV->getType()) 64 OpV = Builder.CreateSExt(OpV, Ty); 65 66 if (Ty != V->getType()) 67 V = Builder.CreateSExt(V, Ty); 68 69 switch (isl_ast_expr_get_op_type(Expr)) { 70 default: 71 llvm_unreachable("This is no n-ary isl ast expression"); 72 73 case isl_ast_op_max: { 74 Value *Cmp = Builder.CreateICmpSGT(V, OpV); 75 V = Builder.CreateSelect(Cmp, V, OpV); 76 continue; 77 } 78 case isl_ast_op_min: { 79 Value *Cmp = Builder.CreateICmpSLT(V, OpV); 80 V = Builder.CreateSelect(Cmp, V, OpV); 81 continue; 82 } 83 } 84 } 85 86 // TODO: We can truncate the result, if it fits into a smaller type. This can 87 // help in cases where we have larger operands (e.g. i67) but the result is 88 // known to fit into i64. Without the truncation, the larger i67 type may 89 // force all subsequent operations to be performed on a non-native type. 90 isl_ast_expr_free(Expr); 91 return V; 92 } 93 94 Value *IslExprBuilder::createOpAccess(isl_ast_expr *Expr) { 95 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 96 "isl ast expression not of type isl_ast_op"); 97 assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_access && 98 "not an access isl ast expression"); 99 assert(isl_ast_expr_get_op_n_arg(Expr) >= 2 && 100 "We need at least two operands to create a member access."); 101 102 // TODO: Support for multi-dimensional array. 103 assert(isl_ast_expr_get_op_n_arg(Expr) == 2 && 104 "Multidimensional access functions are not supported yet"); 105 106 Value *Base, *IndexOp, *Zero, *Access; 107 SmallVector<Value *, 4> Indices; 108 Type *PtrElTy; 109 110 Base = create(isl_ast_expr_get_op_arg(Expr, 0)); 111 assert(Base->getType()->isPointerTy() && "Access base should be a pointer"); 112 113 IndexOp = create(isl_ast_expr_get_op_arg(Expr, 1)); 114 assert(IndexOp->getType()->isIntegerTy() && 115 "Access index should be an integer"); 116 Zero = ConstantInt::getNullValue(IndexOp->getType()); 117 118 // If base is a array type like, 119 // int A[N][M][K]; 120 // we have to adjust the GEP. The easiest way is to transform accesses like, 121 // A[i][j][k] 122 // into equivalent ones like, 123 // A[0][0][ i*N*M + j*M + k] 124 // because SCEV already folded the "peudo dimensions" into one. Thus our index 125 // operand will be 'i*N*M + j*M + k' anyway. 126 PtrElTy = Base->getType()->getPointerElementType(); 127 while (PtrElTy->isArrayTy()) { 128 Indices.push_back(Zero); 129 PtrElTy = PtrElTy->getArrayElementType(); 130 } 131 132 Indices.push_back(IndexOp); 133 assert((PtrElTy->isIntOrIntVectorTy() || PtrElTy->isFPOrFPVectorTy()) && 134 "We do not yet change the type of the access base during code " 135 "generation."); 136 137 Access = Builder.CreateGEP(Base, Indices, "polly.access." + Base->getName()); 138 139 isl_ast_expr_free(Expr); 140 return Access; 141 } 142 143 Value *IslExprBuilder::createOpBin(__isl_take isl_ast_expr *Expr) { 144 Value *LHS, *RHS, *Res; 145 Type *MaxType; 146 isl_ast_op_type OpType; 147 148 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 149 "isl ast expression not of type isl_ast_op"); 150 assert(isl_ast_expr_get_op_n_arg(Expr) == 2 && 151 "not a binary isl ast expression"); 152 153 OpType = isl_ast_expr_get_op_type(Expr); 154 155 LHS = create(isl_ast_expr_get_op_arg(Expr, 0)); 156 RHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 157 158 MaxType = LHS->getType(); 159 MaxType = getWidestType(MaxType, RHS->getType()); 160 161 // Take the result into account when calculating the widest type. 162 // 163 // For operations such as '+' the result may require a type larger than 164 // the type of the individual operands. For other operations such as '/', the 165 // result type cannot be larger than the type of the individual operand. isl 166 // does not calculate correct types for these operations and we consequently 167 // exclude those operations here. 168 switch (OpType) { 169 case isl_ast_op_pdiv_q: 170 case isl_ast_op_pdiv_r: 171 case isl_ast_op_div: 172 case isl_ast_op_fdiv_q: 173 // Do nothing 174 break; 175 case isl_ast_op_add: 176 case isl_ast_op_sub: 177 case isl_ast_op_mul: 178 MaxType = getWidestType(MaxType, getType(Expr)); 179 break; 180 default: 181 llvm_unreachable("This is no binary isl ast expression"); 182 } 183 184 if (MaxType != RHS->getType()) 185 RHS = Builder.CreateSExt(RHS, MaxType); 186 187 if (MaxType != LHS->getType()) 188 LHS = Builder.CreateSExt(LHS, MaxType); 189 190 switch (OpType) { 191 default: 192 llvm_unreachable("This is no binary isl ast expression"); 193 case isl_ast_op_add: 194 Res = Builder.CreateNSWAdd(LHS, RHS); 195 break; 196 case isl_ast_op_sub: 197 Res = Builder.CreateNSWSub(LHS, RHS); 198 break; 199 case isl_ast_op_mul: 200 Res = Builder.CreateNSWMul(LHS, RHS); 201 break; 202 case isl_ast_op_div: 203 case isl_ast_op_pdiv_q: // Dividend is non-negative 204 Res = Builder.CreateSDiv(LHS, RHS); 205 break; 206 case isl_ast_op_fdiv_q: { // Round towards -infty 207 // TODO: Review code and check that this calculation does not yield 208 // incorrect overflow in some bordercases. 209 // 210 // floord(n,d) ((n < 0) ? (n - d + 1) : n) / d 211 Value *One = ConstantInt::get(MaxType, 1); 212 Value *Zero = ConstantInt::get(MaxType, 0); 213 Value *Sum1 = Builder.CreateSub(LHS, RHS); 214 Value *Sum2 = Builder.CreateAdd(Sum1, One); 215 Value *isNegative = Builder.CreateICmpSLT(LHS, Zero); 216 Value *Dividend = Builder.CreateSelect(isNegative, Sum2, LHS); 217 Res = Builder.CreateSDiv(Dividend, RHS); 218 break; 219 } 220 case isl_ast_op_pdiv_r: // Dividend is non-negative 221 Res = Builder.CreateSRem(LHS, RHS); 222 break; 223 } 224 225 // TODO: We can truncate the result, if it fits into a smaller type. This can 226 // help in cases where we have larger operands (e.g. i67) but the result is 227 // known to fit into i64. Without the truncation, the larger i67 type may 228 // force all subsequent operations to be performed on a non-native type. 229 isl_ast_expr_free(Expr); 230 return Res; 231 } 232 233 Value *IslExprBuilder::createOpSelect(__isl_take isl_ast_expr *Expr) { 234 assert(isl_ast_expr_get_op_type(Expr) == isl_ast_op_select && 235 "Unsupported unary isl ast expression"); 236 Value *LHS, *RHS, *Cond; 237 Type *MaxType = getType(Expr); 238 239 Cond = create(isl_ast_expr_get_op_arg(Expr, 0)); 240 241 LHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 242 RHS = create(isl_ast_expr_get_op_arg(Expr, 2)); 243 244 MaxType = getWidestType(MaxType, LHS->getType()); 245 MaxType = getWidestType(MaxType, RHS->getType()); 246 247 if (MaxType != RHS->getType()) 248 RHS = Builder.CreateSExt(RHS, MaxType); 249 250 if (MaxType != LHS->getType()) 251 LHS = Builder.CreateSExt(LHS, MaxType); 252 253 // TODO: Do we want to truncate the result? 254 isl_ast_expr_free(Expr); 255 return Builder.CreateSelect(Cond, LHS, RHS); 256 } 257 258 Value *IslExprBuilder::createOpICmp(__isl_take isl_ast_expr *Expr) { 259 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 260 "Expected an isl_ast_expr_op expression"); 261 262 Value *LHS, *RHS, *Res; 263 264 LHS = create(isl_ast_expr_get_op_arg(Expr, 0)); 265 RHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 266 267 Type *MaxType = LHS->getType(); 268 MaxType = getWidestType(MaxType, RHS->getType()); 269 270 if (MaxType != RHS->getType()) 271 RHS = Builder.CreateSExt(RHS, MaxType); 272 273 if (MaxType != LHS->getType()) 274 LHS = Builder.CreateSExt(LHS, MaxType); 275 276 switch (isl_ast_expr_get_op_type(Expr)) { 277 default: 278 llvm_unreachable("Unsupported ICmp isl ast expression"); 279 case isl_ast_op_eq: 280 Res = Builder.CreateICmpEQ(LHS, RHS); 281 break; 282 case isl_ast_op_le: 283 Res = Builder.CreateICmpSLE(LHS, RHS); 284 break; 285 case isl_ast_op_lt: 286 Res = Builder.CreateICmpSLT(LHS, RHS); 287 break; 288 case isl_ast_op_ge: 289 Res = Builder.CreateICmpSGE(LHS, RHS); 290 break; 291 case isl_ast_op_gt: 292 Res = Builder.CreateICmpSGT(LHS, RHS); 293 break; 294 } 295 296 isl_ast_expr_free(Expr); 297 return Res; 298 } 299 300 Value *IslExprBuilder::createOpBoolean(__isl_take isl_ast_expr *Expr) { 301 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 302 "Expected an isl_ast_expr_op expression"); 303 304 Value *LHS, *RHS, *Res; 305 isl_ast_op_type OpType; 306 307 OpType = isl_ast_expr_get_op_type(Expr); 308 309 assert((OpType == isl_ast_op_and || OpType == isl_ast_op_or) && 310 "Unsupported isl_ast_op_type"); 311 312 LHS = create(isl_ast_expr_get_op_arg(Expr, 0)); 313 RHS = create(isl_ast_expr_get_op_arg(Expr, 1)); 314 315 // Even though the isl pretty printer prints the expressions as 'exp && exp' 316 // or 'exp || exp', we actually code generate the bitwise expressions 317 // 'exp & exp' or 'exp | exp'. This forces the evaluation of both branches, 318 // but it is, due to the use of i1 types, otherwise equivalent. The reason 319 // to go for bitwise operations is, that we assume the reduced control flow 320 // will outweight the overhead introduced by evaluating unneeded expressions. 321 // The isl code generation currently does not take advantage of the fact that 322 // the expression after an '||' or '&&' is in some cases not evaluated. 323 // Evaluating it anyways does not cause any undefined behaviour. 324 // 325 // TODO: Document in isl itself, that the unconditionally evaluating the 326 // second part of '||' or '&&' expressions is safe. 327 assert(LHS->getType() == Builder.getInt1Ty() && "Expected i1 type"); 328 assert(RHS->getType() == Builder.getInt1Ty() && "Expected i1 type"); 329 330 switch (OpType) { 331 default: 332 llvm_unreachable("Unsupported boolean expression"); 333 case isl_ast_op_and: 334 Res = Builder.CreateAnd(LHS, RHS); 335 break; 336 case isl_ast_op_or: 337 Res = Builder.CreateOr(LHS, RHS); 338 break; 339 } 340 341 isl_ast_expr_free(Expr); 342 return Res; 343 } 344 345 Value *IslExprBuilder::createOp(__isl_take isl_ast_expr *Expr) { 346 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_op && 347 "Expression not of type isl_ast_expr_op"); 348 switch (isl_ast_expr_get_op_type(Expr)) { 349 case isl_ast_op_error: 350 case isl_ast_op_cond: 351 case isl_ast_op_and_then: 352 case isl_ast_op_or_else: 353 case isl_ast_op_call: 354 case isl_ast_op_member: 355 llvm_unreachable("Unsupported isl ast expression"); 356 case isl_ast_op_access: 357 return createOpAccess(Expr); 358 case isl_ast_op_max: 359 case isl_ast_op_min: 360 return createOpNAry(Expr); 361 case isl_ast_op_add: 362 case isl_ast_op_sub: 363 case isl_ast_op_mul: 364 case isl_ast_op_div: 365 case isl_ast_op_fdiv_q: // Round towards -infty 366 case isl_ast_op_pdiv_q: // Dividend is non-negative 367 case isl_ast_op_pdiv_r: // Dividend is non-negative 368 return createOpBin(Expr); 369 case isl_ast_op_minus: 370 return createOpUnary(Expr); 371 case isl_ast_op_select: 372 return createOpSelect(Expr); 373 case isl_ast_op_and: 374 case isl_ast_op_or: 375 return createOpBoolean(Expr); 376 case isl_ast_op_eq: 377 case isl_ast_op_le: 378 case isl_ast_op_lt: 379 case isl_ast_op_ge: 380 case isl_ast_op_gt: 381 return createOpICmp(Expr); 382 } 383 384 llvm_unreachable("Unsupported isl_ast_expr_op kind."); 385 } 386 387 Value *IslExprBuilder::createId(__isl_take isl_ast_expr *Expr) { 388 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_id && 389 "Expression not of type isl_ast_expr_ident"); 390 391 isl_id *Id; 392 Value *V; 393 394 Id = isl_ast_expr_get_id(Expr); 395 396 assert(IDToValue.count(Id) && "Identifier not found"); 397 398 V = IDToValue[Id]; 399 400 isl_id_free(Id); 401 isl_ast_expr_free(Expr); 402 403 return V; 404 } 405 406 IntegerType *IslExprBuilder::getType(__isl_keep isl_ast_expr *Expr) { 407 // XXX: We assume i64 is large enough. This is often true, but in general 408 // incorrect. Also, on 32bit architectures, it would be beneficial to 409 // use a smaller type. We can and should directly derive this information 410 // during code generation. 411 return IntegerType::get(Builder.getContext(), 64); 412 } 413 414 Value *IslExprBuilder::createInt(__isl_take isl_ast_expr *Expr) { 415 assert(isl_ast_expr_get_type(Expr) == isl_ast_expr_int && 416 "Expression not of type isl_ast_expr_int"); 417 isl_val *Val; 418 Value *V; 419 APInt APValue; 420 IntegerType *T; 421 422 Val = isl_ast_expr_get_val(Expr); 423 APValue = APIntFromVal(Val); 424 T = getType(Expr); 425 APValue = APValue.sextOrSelf(T->getBitWidth()); 426 V = ConstantInt::get(T, APValue); 427 428 isl_ast_expr_free(Expr); 429 return V; 430 } 431 432 Value *IslExprBuilder::create(__isl_take isl_ast_expr *Expr) { 433 switch (isl_ast_expr_get_type(Expr)) { 434 case isl_ast_expr_error: 435 llvm_unreachable("Code generation error"); 436 case isl_ast_expr_op: 437 return createOp(Expr); 438 case isl_ast_expr_id: 439 return createId(Expr); 440 case isl_ast_expr_int: 441 return createInt(Expr); 442 } 443 444 llvm_unreachable("Unexpected enum value"); 445 } 446