1 //===- MemRefBuilder.cpp - Helper for LLVM MemRef equivalents -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "mlir/Conversion/LLVMCommon/MemRefBuilder.h" 10 #include "MemRefDescriptor.h" 11 #include "mlir/Conversion/LLVMCommon/TypeConverter.h" 12 #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 13 #include "mlir/Dialect/LLVMIR/LLVMTypes.h" 14 #include "mlir/IR/Builders.h" 15 #include "llvm/Support/MathExtras.h" 16 17 using namespace mlir; 18 19 //===----------------------------------------------------------------------===// 20 // MemRefDescriptor implementation 21 //===----------------------------------------------------------------------===// 22 23 /// Construct a helper for the given descriptor value. 24 MemRefDescriptor::MemRefDescriptor(Value descriptor) 25 : StructBuilder(descriptor) { 26 assert(value != nullptr && "value cannot be null"); 27 indexType = cast<LLVM::LLVMStructType>(value.getType()) 28 .getBody()[kOffsetPosInMemRefDescriptor]; 29 } 30 31 /// Builds IR creating an `undef` value of the descriptor type. 32 MemRefDescriptor MemRefDescriptor::undef(OpBuilder &builder, Location loc, 33 Type descriptorType) { 34 35 Value descriptor = builder.create<LLVM::UndefOp>(loc, descriptorType); 36 return MemRefDescriptor(descriptor); 37 } 38 39 /// Builds IR creating a MemRef descriptor that represents `type` and 40 /// populates it with static shape and stride information extracted from the 41 /// type. 42 MemRefDescriptor 43 MemRefDescriptor::fromStaticShape(OpBuilder &builder, Location loc, 44 const LLVMTypeConverter &typeConverter, 45 MemRefType type, Value memory) { 46 return fromStaticShape(builder, loc, typeConverter, type, memory, memory); 47 } 48 49 MemRefDescriptor MemRefDescriptor::fromStaticShape( 50 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 51 MemRefType type, Value memory, Value alignedMemory) { 52 assert(type.hasStaticShape() && "unexpected dynamic shape"); 53 54 // Extract all strides and offsets and verify they are static. 55 auto [strides, offset] = type.getStridesAndOffset(); 56 assert(!ShapedType::isDynamic(offset) && "expected static offset"); 57 assert(!llvm::any_of(strides, ShapedType::isDynamic) && 58 "expected static strides"); 59 60 auto convertedType = typeConverter.convertType(type); 61 assert(convertedType && "unexpected failure in memref type conversion"); 62 63 auto descr = MemRefDescriptor::undef(builder, loc, convertedType); 64 descr.setAllocatedPtr(builder, loc, memory); 65 descr.setAlignedPtr(builder, loc, alignedMemory); 66 descr.setConstantOffset(builder, loc, offset); 67 68 // Fill in sizes and strides 69 for (unsigned i = 0, e = type.getRank(); i != e; ++i) { 70 descr.setConstantSize(builder, loc, i, type.getDimSize(i)); 71 descr.setConstantStride(builder, loc, i, strides[i]); 72 } 73 return descr; 74 } 75 76 /// Builds IR extracting the allocated pointer from the descriptor. 77 Value MemRefDescriptor::allocatedPtr(OpBuilder &builder, Location loc) { 78 return extractPtr(builder, loc, kAllocatedPtrPosInMemRefDescriptor); 79 } 80 81 /// Builds IR inserting the allocated pointer into the descriptor. 82 void MemRefDescriptor::setAllocatedPtr(OpBuilder &builder, Location loc, 83 Value ptr) { 84 setPtr(builder, loc, kAllocatedPtrPosInMemRefDescriptor, ptr); 85 } 86 87 /// Builds IR extracting the aligned pointer from the descriptor. 88 Value MemRefDescriptor::alignedPtr(OpBuilder &builder, Location loc) { 89 return extractPtr(builder, loc, kAlignedPtrPosInMemRefDescriptor); 90 } 91 92 /// Builds IR inserting the aligned pointer into the descriptor. 93 void MemRefDescriptor::setAlignedPtr(OpBuilder &builder, Location loc, 94 Value ptr) { 95 setPtr(builder, loc, kAlignedPtrPosInMemRefDescriptor, ptr); 96 } 97 98 // Creates a constant Op producing a value of `resultType` from an index-typed 99 // integer attribute. 100 static Value createIndexAttrConstant(OpBuilder &builder, Location loc, 101 Type resultType, int64_t value) { 102 return builder.create<LLVM::ConstantOp>(loc, resultType, 103 builder.getIndexAttr(value)); 104 } 105 106 /// Builds IR extracting the offset from the descriptor. 107 Value MemRefDescriptor::offset(OpBuilder &builder, Location loc) { 108 return builder.create<LLVM::ExtractValueOp>(loc, value, 109 kOffsetPosInMemRefDescriptor); 110 } 111 112 /// Builds IR inserting the offset into the descriptor. 113 void MemRefDescriptor::setOffset(OpBuilder &builder, Location loc, 114 Value offset) { 115 value = builder.create<LLVM::InsertValueOp>(loc, value, offset, 116 kOffsetPosInMemRefDescriptor); 117 } 118 119 /// Builds IR inserting the offset into the descriptor. 120 void MemRefDescriptor::setConstantOffset(OpBuilder &builder, Location loc, 121 uint64_t offset) { 122 setOffset(builder, loc, 123 createIndexAttrConstant(builder, loc, indexType, offset)); 124 } 125 126 /// Builds IR extracting the pos-th size from the descriptor. 127 Value MemRefDescriptor::size(OpBuilder &builder, Location loc, unsigned pos) { 128 return builder.create<LLVM::ExtractValueOp>( 129 loc, value, ArrayRef<int64_t>({kSizePosInMemRefDescriptor, pos})); 130 } 131 132 Value MemRefDescriptor::size(OpBuilder &builder, Location loc, Value pos, 133 int64_t rank) { 134 auto arrayTy = LLVM::LLVMArrayType::get(indexType, rank); 135 136 auto ptrTy = LLVM::LLVMPointerType::get(builder.getContext()); 137 138 // Copy size values to stack-allocated memory. 139 auto one = createIndexAttrConstant(builder, loc, indexType, 1); 140 auto sizes = builder.create<LLVM::ExtractValueOp>( 141 loc, value, llvm::ArrayRef<int64_t>({kSizePosInMemRefDescriptor})); 142 auto sizesPtr = builder.create<LLVM::AllocaOp>(loc, ptrTy, arrayTy, one, 143 /*alignment=*/0); 144 builder.create<LLVM::StoreOp>(loc, sizes, sizesPtr); 145 146 // Load an return size value of interest. 147 auto resultPtr = builder.create<LLVM::GEPOp>(loc, ptrTy, arrayTy, sizesPtr, 148 ArrayRef<LLVM::GEPArg>{0, pos}); 149 return builder.create<LLVM::LoadOp>(loc, indexType, resultPtr); 150 } 151 152 /// Builds IR inserting the pos-th size into the descriptor 153 void MemRefDescriptor::setSize(OpBuilder &builder, Location loc, unsigned pos, 154 Value size) { 155 value = builder.create<LLVM::InsertValueOp>( 156 loc, value, size, ArrayRef<int64_t>({kSizePosInMemRefDescriptor, pos})); 157 } 158 159 void MemRefDescriptor::setConstantSize(OpBuilder &builder, Location loc, 160 unsigned pos, uint64_t size) { 161 setSize(builder, loc, pos, 162 createIndexAttrConstant(builder, loc, indexType, size)); 163 } 164 165 /// Builds IR extracting the pos-th stride from the descriptor. 166 Value MemRefDescriptor::stride(OpBuilder &builder, Location loc, unsigned pos) { 167 return builder.create<LLVM::ExtractValueOp>( 168 loc, value, ArrayRef<int64_t>({kStridePosInMemRefDescriptor, pos})); 169 } 170 171 /// Builds IR inserting the pos-th stride into the descriptor 172 void MemRefDescriptor::setStride(OpBuilder &builder, Location loc, unsigned pos, 173 Value stride) { 174 value = builder.create<LLVM::InsertValueOp>( 175 loc, value, stride, 176 ArrayRef<int64_t>({kStridePosInMemRefDescriptor, pos})); 177 } 178 179 void MemRefDescriptor::setConstantStride(OpBuilder &builder, Location loc, 180 unsigned pos, uint64_t stride) { 181 setStride(builder, loc, pos, 182 createIndexAttrConstant(builder, loc, indexType, stride)); 183 } 184 185 LLVM::LLVMPointerType MemRefDescriptor::getElementPtrType() { 186 return cast<LLVM::LLVMPointerType>( 187 cast<LLVM::LLVMStructType>(value.getType()) 188 .getBody()[kAlignedPtrPosInMemRefDescriptor]); 189 } 190 191 Value MemRefDescriptor::bufferPtr(OpBuilder &builder, Location loc, 192 const LLVMTypeConverter &converter, 193 MemRefType type) { 194 // When we convert to LLVM, the input memref must have been normalized 195 // beforehand. Hence, this call is guaranteed to work. 196 auto [strides, offsetCst] = type.getStridesAndOffset(); 197 198 Value ptr = alignedPtr(builder, loc); 199 // For zero offsets, we already have the base pointer. 200 if (offsetCst == 0) 201 return ptr; 202 203 // Otherwise add the offset to the aligned base. 204 Type indexType = converter.getIndexType(); 205 Value offsetVal = 206 ShapedType::isDynamic(offsetCst) 207 ? offset(builder, loc) 208 : createIndexAttrConstant(builder, loc, indexType, offsetCst); 209 Type elementType = converter.convertType(type.getElementType()); 210 ptr = builder.create<LLVM::GEPOp>(loc, ptr.getType(), elementType, ptr, 211 offsetVal); 212 return ptr; 213 } 214 215 /// Creates a MemRef descriptor structure from a list of individual values 216 /// composing that descriptor, in the following order: 217 /// - allocated pointer; 218 /// - aligned pointer; 219 /// - offset; 220 /// - <rank> sizes; 221 /// - <rank> strides; 222 /// where <rank> is the MemRef rank as provided in `type`. 223 Value MemRefDescriptor::pack(OpBuilder &builder, Location loc, 224 const LLVMTypeConverter &converter, 225 MemRefType type, ValueRange values) { 226 Type llvmType = converter.convertType(type); 227 auto d = MemRefDescriptor::undef(builder, loc, llvmType); 228 229 d.setAllocatedPtr(builder, loc, values[kAllocatedPtrPosInMemRefDescriptor]); 230 d.setAlignedPtr(builder, loc, values[kAlignedPtrPosInMemRefDescriptor]); 231 d.setOffset(builder, loc, values[kOffsetPosInMemRefDescriptor]); 232 233 int64_t rank = type.getRank(); 234 for (unsigned i = 0; i < rank; ++i) { 235 d.setSize(builder, loc, i, values[kSizePosInMemRefDescriptor + i]); 236 d.setStride(builder, loc, i, values[kSizePosInMemRefDescriptor + rank + i]); 237 } 238 239 return d; 240 } 241 242 /// Builds IR extracting individual elements of a MemRef descriptor structure 243 /// and returning them as `results` list. 244 void MemRefDescriptor::unpack(OpBuilder &builder, Location loc, Value packed, 245 MemRefType type, 246 SmallVectorImpl<Value> &results) { 247 int64_t rank = type.getRank(); 248 results.reserve(results.size() + getNumUnpackedValues(type)); 249 250 MemRefDescriptor d(packed); 251 results.push_back(d.allocatedPtr(builder, loc)); 252 results.push_back(d.alignedPtr(builder, loc)); 253 results.push_back(d.offset(builder, loc)); 254 for (int64_t i = 0; i < rank; ++i) 255 results.push_back(d.size(builder, loc, i)); 256 for (int64_t i = 0; i < rank; ++i) 257 results.push_back(d.stride(builder, loc, i)); 258 } 259 260 /// Returns the number of non-aggregate values that would be produced by 261 /// `unpack`. 262 unsigned MemRefDescriptor::getNumUnpackedValues(MemRefType type) { 263 // Two pointers, offset, <rank> sizes, <rank> strides. 264 return 3 + 2 * type.getRank(); 265 } 266 267 //===----------------------------------------------------------------------===// 268 // MemRefDescriptorView implementation. 269 //===----------------------------------------------------------------------===// 270 271 MemRefDescriptorView::MemRefDescriptorView(ValueRange range) 272 : rank((range.size() - kSizePosInMemRefDescriptor) / 2), elements(range) {} 273 274 Value MemRefDescriptorView::allocatedPtr() { 275 return elements[kAllocatedPtrPosInMemRefDescriptor]; 276 } 277 278 Value MemRefDescriptorView::alignedPtr() { 279 return elements[kAlignedPtrPosInMemRefDescriptor]; 280 } 281 282 Value MemRefDescriptorView::offset() { 283 return elements[kOffsetPosInMemRefDescriptor]; 284 } 285 286 Value MemRefDescriptorView::size(unsigned pos) { 287 return elements[kSizePosInMemRefDescriptor + pos]; 288 } 289 290 Value MemRefDescriptorView::stride(unsigned pos) { 291 return elements[kSizePosInMemRefDescriptor + rank + pos]; 292 } 293 294 //===----------------------------------------------------------------------===// 295 // UnrankedMemRefDescriptor implementation 296 //===----------------------------------------------------------------------===// 297 298 /// Construct a helper for the given descriptor value. 299 UnrankedMemRefDescriptor::UnrankedMemRefDescriptor(Value descriptor) 300 : StructBuilder(descriptor) {} 301 302 /// Builds IR creating an `undef` value of the descriptor type. 303 UnrankedMemRefDescriptor UnrankedMemRefDescriptor::undef(OpBuilder &builder, 304 Location loc, 305 Type descriptorType) { 306 Value descriptor = builder.create<LLVM::UndefOp>(loc, descriptorType); 307 return UnrankedMemRefDescriptor(descriptor); 308 } 309 Value UnrankedMemRefDescriptor::rank(OpBuilder &builder, Location loc) const { 310 return extractPtr(builder, loc, kRankInUnrankedMemRefDescriptor); 311 } 312 void UnrankedMemRefDescriptor::setRank(OpBuilder &builder, Location loc, 313 Value v) { 314 setPtr(builder, loc, kRankInUnrankedMemRefDescriptor, v); 315 } 316 Value UnrankedMemRefDescriptor::memRefDescPtr(OpBuilder &builder, 317 Location loc) const { 318 return extractPtr(builder, loc, kPtrInUnrankedMemRefDescriptor); 319 } 320 void UnrankedMemRefDescriptor::setMemRefDescPtr(OpBuilder &builder, 321 Location loc, Value v) { 322 setPtr(builder, loc, kPtrInUnrankedMemRefDescriptor, v); 323 } 324 325 /// Builds IR populating an unranked MemRef descriptor structure from a list 326 /// of individual constituent values in the following order: 327 /// - rank of the memref; 328 /// - pointer to the memref descriptor. 329 Value UnrankedMemRefDescriptor::pack(OpBuilder &builder, Location loc, 330 const LLVMTypeConverter &converter, 331 UnrankedMemRefType type, 332 ValueRange values) { 333 Type llvmType = converter.convertType(type); 334 auto d = UnrankedMemRefDescriptor::undef(builder, loc, llvmType); 335 336 d.setRank(builder, loc, values[kRankInUnrankedMemRefDescriptor]); 337 d.setMemRefDescPtr(builder, loc, values[kPtrInUnrankedMemRefDescriptor]); 338 return d; 339 } 340 341 /// Builds IR extracting individual elements that compose an unranked memref 342 /// descriptor and returns them as `results` list. 343 void UnrankedMemRefDescriptor::unpack(OpBuilder &builder, Location loc, 344 Value packed, 345 SmallVectorImpl<Value> &results) { 346 UnrankedMemRefDescriptor d(packed); 347 results.reserve(results.size() + 2); 348 results.push_back(d.rank(builder, loc)); 349 results.push_back(d.memRefDescPtr(builder, loc)); 350 } 351 352 void UnrankedMemRefDescriptor::computeSizes( 353 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 354 ArrayRef<UnrankedMemRefDescriptor> values, ArrayRef<unsigned> addressSpaces, 355 SmallVectorImpl<Value> &sizes) { 356 if (values.empty()) 357 return; 358 assert(values.size() == addressSpaces.size() && 359 "must provide address space for each descriptor"); 360 // Cache the index type. 361 Type indexType = typeConverter.getIndexType(); 362 363 // Initialize shared constants. 364 Value one = createIndexAttrConstant(builder, loc, indexType, 1); 365 Value two = createIndexAttrConstant(builder, loc, indexType, 2); 366 Value indexSize = createIndexAttrConstant( 367 builder, loc, indexType, 368 llvm::divideCeil(typeConverter.getIndexTypeBitwidth(), 8)); 369 370 sizes.reserve(sizes.size() + values.size()); 371 for (auto [desc, addressSpace] : llvm::zip(values, addressSpaces)) { 372 // Emit IR computing the memory necessary to store the descriptor. This 373 // assumes the descriptor to be 374 // { type*, type*, index, index[rank], index[rank] } 375 // and densely packed, so the total size is 376 // 2 * sizeof(pointer) + (1 + 2 * rank) * sizeof(index). 377 // TODO: consider including the actual size (including eventual padding due 378 // to data layout) into the unranked descriptor. 379 Value pointerSize = createIndexAttrConstant( 380 builder, loc, indexType, 381 llvm::divideCeil(typeConverter.getPointerBitwidth(addressSpace), 8)); 382 Value doublePointerSize = 383 builder.create<LLVM::MulOp>(loc, indexType, two, pointerSize); 384 385 // (1 + 2 * rank) * sizeof(index) 386 Value rank = desc.rank(builder, loc); 387 Value doubleRank = builder.create<LLVM::MulOp>(loc, indexType, two, rank); 388 Value doubleRankIncremented = 389 builder.create<LLVM::AddOp>(loc, indexType, doubleRank, one); 390 Value rankIndexSize = builder.create<LLVM::MulOp>( 391 loc, indexType, doubleRankIncremented, indexSize); 392 393 // Total allocation size. 394 Value allocationSize = builder.create<LLVM::AddOp>( 395 loc, indexType, doublePointerSize, rankIndexSize); 396 sizes.push_back(allocationSize); 397 } 398 } 399 400 Value UnrankedMemRefDescriptor::allocatedPtr( 401 OpBuilder &builder, Location loc, Value memRefDescPtr, 402 LLVM::LLVMPointerType elemPtrType) { 403 return builder.create<LLVM::LoadOp>(loc, elemPtrType, memRefDescPtr); 404 } 405 406 void UnrankedMemRefDescriptor::setAllocatedPtr( 407 OpBuilder &builder, Location loc, Value memRefDescPtr, 408 LLVM::LLVMPointerType elemPtrType, Value allocatedPtr) { 409 builder.create<LLVM::StoreOp>(loc, allocatedPtr, memRefDescPtr); 410 } 411 412 static std::pair<Value, Type> 413 castToElemPtrPtr(OpBuilder &builder, Location loc, Value memRefDescPtr, 414 LLVM::LLVMPointerType elemPtrType) { 415 auto elemPtrPtrType = LLVM::LLVMPointerType::get(builder.getContext()); 416 return {memRefDescPtr, elemPtrPtrType}; 417 } 418 419 Value UnrankedMemRefDescriptor::alignedPtr( 420 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 421 Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType) { 422 auto [elementPtrPtr, elemPtrPtrType] = 423 castToElemPtrPtr(builder, loc, memRefDescPtr, elemPtrType); 424 425 Value alignedGep = 426 builder.create<LLVM::GEPOp>(loc, elemPtrPtrType, elemPtrType, 427 elementPtrPtr, ArrayRef<LLVM::GEPArg>{1}); 428 return builder.create<LLVM::LoadOp>(loc, elemPtrType, alignedGep); 429 } 430 431 void UnrankedMemRefDescriptor::setAlignedPtr( 432 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 433 Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType, Value alignedPtr) { 434 auto [elementPtrPtr, elemPtrPtrType] = 435 castToElemPtrPtr(builder, loc, memRefDescPtr, elemPtrType); 436 437 Value alignedGep = 438 builder.create<LLVM::GEPOp>(loc, elemPtrPtrType, elemPtrType, 439 elementPtrPtr, ArrayRef<LLVM::GEPArg>{1}); 440 builder.create<LLVM::StoreOp>(loc, alignedPtr, alignedGep); 441 } 442 443 Value UnrankedMemRefDescriptor::offsetBasePtr( 444 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 445 Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType) { 446 auto [elementPtrPtr, elemPtrPtrType] = 447 castToElemPtrPtr(builder, loc, memRefDescPtr, elemPtrType); 448 449 return builder.create<LLVM::GEPOp>(loc, elemPtrPtrType, elemPtrType, 450 elementPtrPtr, ArrayRef<LLVM::GEPArg>{2}); 451 } 452 453 Value UnrankedMemRefDescriptor::offset(OpBuilder &builder, Location loc, 454 const LLVMTypeConverter &typeConverter, 455 Value memRefDescPtr, 456 LLVM::LLVMPointerType elemPtrType) { 457 Value offsetPtr = 458 offsetBasePtr(builder, loc, typeConverter, memRefDescPtr, elemPtrType); 459 return builder.create<LLVM::LoadOp>(loc, typeConverter.getIndexType(), 460 offsetPtr); 461 } 462 463 void UnrankedMemRefDescriptor::setOffset(OpBuilder &builder, Location loc, 464 const LLVMTypeConverter &typeConverter, 465 Value memRefDescPtr, 466 LLVM::LLVMPointerType elemPtrType, 467 Value offset) { 468 Value offsetPtr = 469 offsetBasePtr(builder, loc, typeConverter, memRefDescPtr, elemPtrType); 470 builder.create<LLVM::StoreOp>(loc, offset, offsetPtr); 471 } 472 473 Value UnrankedMemRefDescriptor::sizeBasePtr( 474 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 475 Value memRefDescPtr, LLVM::LLVMPointerType elemPtrType) { 476 Type indexTy = typeConverter.getIndexType(); 477 Type structTy = LLVM::LLVMStructType::getLiteral( 478 indexTy.getContext(), {elemPtrType, elemPtrType, indexTy, indexTy}); 479 auto resultType = LLVM::LLVMPointerType::get(builder.getContext()); 480 return builder.create<LLVM::GEPOp>(loc, resultType, structTy, memRefDescPtr, 481 ArrayRef<LLVM::GEPArg>{0, 3}); 482 } 483 484 Value UnrankedMemRefDescriptor::size(OpBuilder &builder, Location loc, 485 const LLVMTypeConverter &typeConverter, 486 Value sizeBasePtr, Value index) { 487 488 Type indexTy = typeConverter.getIndexType(); 489 auto ptrType = LLVM::LLVMPointerType::get(builder.getContext()); 490 491 Value sizeStoreGep = 492 builder.create<LLVM::GEPOp>(loc, ptrType, indexTy, sizeBasePtr, index); 493 return builder.create<LLVM::LoadOp>(loc, indexTy, sizeStoreGep); 494 } 495 496 void UnrankedMemRefDescriptor::setSize(OpBuilder &builder, Location loc, 497 const LLVMTypeConverter &typeConverter, 498 Value sizeBasePtr, Value index, 499 Value size) { 500 Type indexTy = typeConverter.getIndexType(); 501 auto ptrType = LLVM::LLVMPointerType::get(builder.getContext()); 502 503 Value sizeStoreGep = 504 builder.create<LLVM::GEPOp>(loc, ptrType, indexTy, sizeBasePtr, index); 505 builder.create<LLVM::StoreOp>(loc, size, sizeStoreGep); 506 } 507 508 Value UnrankedMemRefDescriptor::strideBasePtr( 509 OpBuilder &builder, Location loc, const LLVMTypeConverter &typeConverter, 510 Value sizeBasePtr, Value rank) { 511 Type indexTy = typeConverter.getIndexType(); 512 auto ptrType = LLVM::LLVMPointerType::get(builder.getContext()); 513 514 return builder.create<LLVM::GEPOp>(loc, ptrType, indexTy, sizeBasePtr, rank); 515 } 516 517 Value UnrankedMemRefDescriptor::stride(OpBuilder &builder, Location loc, 518 const LLVMTypeConverter &typeConverter, 519 Value strideBasePtr, Value index, 520 Value stride) { 521 Type indexTy = typeConverter.getIndexType(); 522 auto ptrType = LLVM::LLVMPointerType::get(builder.getContext()); 523 524 Value strideStoreGep = 525 builder.create<LLVM::GEPOp>(loc, ptrType, indexTy, strideBasePtr, index); 526 return builder.create<LLVM::LoadOp>(loc, indexTy, strideStoreGep); 527 } 528 529 void UnrankedMemRefDescriptor::setStride(OpBuilder &builder, Location loc, 530 const LLVMTypeConverter &typeConverter, 531 Value strideBasePtr, Value index, 532 Value stride) { 533 Type indexTy = typeConverter.getIndexType(); 534 auto ptrType = LLVM::LLVMPointerType::get(builder.getContext()); 535 536 Value strideStoreGep = 537 builder.create<LLVM::GEPOp>(loc, ptrType, indexTy, strideBasePtr, index); 538 builder.create<LLVM::StoreOp>(loc, stride, strideStoreGep); 539 } 540