diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -969,17 +969,40 @@ /*isVarArg=*/false)); } -/// Helper function for generating the LLVM IR that computes the size -/// in bytes for a derived type. +/// Helper function for generating the LLVM IR that computes the distance +/// in bytes between adjacent elements pointed to by a pointer +/// of type \p ptrTy. The result is returned as a value of \p idxTy integer +/// type. static mlir::Value -computeDerivedTypeSize(mlir::Location loc, mlir::Type ptrTy, mlir::Type idxTy, +computeElementDistance(mlir::Location loc, mlir::Type ptrTy, mlir::Type idxTy, mlir::ConversionPatternRewriter &rewriter) { + // Note that we cannot use something like + // mlir::LLVM::getPrimitiveTypeSizeInBits() for the element type here. For + // example, it returns 10 bytes for mlir::Float80Type for targets where it + // occupies 16 bytes. Proper solution is probably to use + // mlir::DataLayout::getTypeABIAlignment(), but DataLayout is not being set + // yet (see llvm-project#57230). For the time being use the '(intptr_t)((type + // *)0 + 1)' trick for all types. The generated instructions are optimized + // into constant by the first pass of InstCombine, so it should not be a + // performance issue. auto nullPtr = rewriter.create(loc, ptrTy); auto gep = rewriter.create( loc, ptrTy, nullPtr, llvm::ArrayRef{1}); return rewriter.create(loc, idxTy, gep); } +/// Return value of the stride in bytes between adjacent elements +/// of LLVM type \p llTy. The result is returned as a value of +/// \p idxTy integer type. +static mlir::Value +genTypeStrideInBytes(mlir::Location loc, mlir::Type idxTy, + mlir::ConversionPatternRewriter &rewriter, + mlir::Type llTy) { + // Create a pointer type and use computeElementDistance(). + auto ptrTy = mlir::LLVM::LLVMPointerType::get(llTy); + return computeElementDistance(loc, ptrTy, idxTy, rewriter); +} + namespace { /// Lower a `fir.allocmem` instruction into `llvm.call @malloc` struct AllocMemOpConversion : public FIROpConversion { @@ -1010,18 +1033,14 @@ return mlir::success(); } - // Compute the (allocation) size of the allocmem type in bytes. + /// Compute the allocation size in bytes of the element type of + /// \p llTy pointer type. The result is returned as a value of \p idxTy + /// integer type. mlir::Value genTypeSizeInBytes(mlir::Location loc, mlir::Type idxTy, mlir::ConversionPatternRewriter &rewriter, mlir::Type llTy) const { - // Use the primitive size, if available. auto ptrTy = llTy.dyn_cast(); - if (auto size = - mlir::LLVM::getPrimitiveTypeSizeInBits(ptrTy.getElementType())) - return genConstantIndex(loc, idxTy, rewriter, size / 8); - - // Otherwise, generate the GEP trick in LLVM IR to compute the size. - return computeDerivedTypeSize(loc, ptrTy, idxTy, rewriter); + return computeElementDistance(loc, ptrTy, idxTy, rewriter); } }; } // namespace @@ -1127,45 +1146,66 @@ std::tuple getSizeAndTypeCode( mlir::Location loc, mlir::ConversionPatternRewriter &rewriter, mlir::Type boxEleTy, mlir::ValueRange lenParams = {}) const { + auto i64Ty = mlir::IntegerType::get(rewriter.getContext(), 64); + auto getKindMap = [&]() -> fir::KindMapping & { + return this->lowerTy().getKindMap(); + }; auto doInteger = - [&](unsigned width) -> std::tuple { + [&](mlir::Type type, + unsigned width) -> std::tuple { int typeCode = fir::integerBitsToTypeCode(width); - return {this->genConstantOffset(loc, rewriter, width / 8), - this->genConstantOffset(loc, rewriter, typeCode)}; + return { + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), + this->genConstantOffset(loc, rewriter, typeCode)}; }; auto doLogical = - [&](unsigned width) -> std::tuple { + [&](mlir::Type type, + unsigned width) -> std::tuple { int typeCode = fir::logicalBitsToTypeCode(width); - return {this->genConstantOffset(loc, rewriter, width / 8), - this->genConstantOffset(loc, rewriter, typeCode)}; + return { + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), + this->genConstantOffset(loc, rewriter, typeCode)}; }; - auto doFloat = [&](unsigned width) -> std::tuple { + auto doFloat = [&](mlir::Type type, + unsigned width) -> std::tuple { int typeCode = fir::realBitsToTypeCode(width); - return {this->genConstantOffset(loc, rewriter, width / 8), - this->genConstantOffset(loc, rewriter, typeCode)}; + return { + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), + this->genConstantOffset(loc, rewriter, typeCode)}; }; auto doComplex = - [&](unsigned width) -> std::tuple { + [&](mlir::Type type, + unsigned width) -> std::tuple { auto typeCode = fir::complexBitsToTypeCode(width); - return {this->genConstantOffset(loc, rewriter, width / 8 * 2), - this->genConstantOffset(loc, rewriter, typeCode)}; + return { + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)), + this->genConstantOffset(loc, rewriter, typeCode)}; }; - auto doCharacter = - [&](unsigned width, - mlir::Value len) -> std::tuple { - auto typeCode = fir::characterBitsToTypeCode(width); + auto doCharacter = [&](fir::CharacterType type, mlir::ValueRange lenParams) + -> std::tuple { + unsigned bitWidth = getKindMap().getCharacterBitsize(type.getFKind()); + auto typeCode = fir::characterBitsToTypeCode(bitWidth); auto typeCodeVal = this->genConstantOffset(loc, rewriter, typeCode); - if (width == 8) - return {len, typeCodeVal}; - auto i64Ty = mlir::IntegerType::get(&this->lowerTy().getContext(), 64); - auto byteWidth = genConstantIndex(loc, i64Ty, rewriter, width / 8); - auto len64 = FIROpConversion::integerCast(loc, rewriter, i64Ty, len); - auto size = - rewriter.create(loc, i64Ty, byteWidth, len64); - return {size, typeCodeVal}; - }; - auto getKindMap = [&]() -> fir::KindMapping & { - return this->lowerTy().getKindMap(); + + bool lengthIsConst = (type.getLen() != fir::CharacterType::unknownLen()); + mlir::Value eleSize = + genTypeStrideInBytes(loc, i64Ty, rewriter, this->convertType(type)); + + if (!lengthIsConst) { + // If length is constant, then the fir::CharacterType will be + // represented as an array of known size of elements having + // the corresponding LLVM type. In this case eleSize already + // holds correct memory size. If length is not constant, then + // the fir::CharacterType will decay to a scalar type, + // so we have to multiply it by the non-constant length + // to get its size in memory. + assert(!lenParams.empty()); + auto len64 = FIROpConversion::integerCast(loc, rewriter, i64Ty, + lenParams.back()); + eleSize = + rewriter.create(loc, i64Ty, eleSize, len64); + } + return {eleSize, typeCodeVal}; }; // Pointer-like types. if (auto eleTy = fir::dyn_cast_ptrEleTy(boxEleTy)) @@ -1173,58 +1213,47 @@ // Integer types. if (fir::isa_integer(boxEleTy)) { if (auto ty = boxEleTy.dyn_cast()) - return doInteger(ty.getWidth()); + return doInteger(ty, ty.getWidth()); auto ty = boxEleTy.cast(); - return doInteger(getKindMap().getIntegerBitsize(ty.getFKind())); + return doInteger(ty, getKindMap().getIntegerBitsize(ty.getFKind())); } // Floating point types. if (fir::isa_real(boxEleTy)) { if (auto ty = boxEleTy.dyn_cast()) - return doFloat(ty.getWidth()); + return doFloat(ty, ty.getWidth()); auto ty = boxEleTy.cast(); - return doFloat(getKindMap().getRealBitsize(ty.getFKind())); + return doFloat(ty, getKindMap().getRealBitsize(ty.getFKind())); } // Complex types. if (fir::isa_complex(boxEleTy)) { if (auto ty = boxEleTy.dyn_cast()) return doComplex( - ty.getElementType().cast().getWidth()); + ty, ty.getElementType().cast().getWidth()); auto ty = boxEleTy.cast(); - return doComplex(getKindMap().getRealBitsize(ty.getFKind())); + return doComplex(ty, getKindMap().getRealBitsize(ty.getFKind())); } // Character types. - if (auto ty = boxEleTy.dyn_cast()) { - auto charWidth = getKindMap().getCharacterBitsize(ty.getFKind()); - if (ty.getLen() != fir::CharacterType::unknownLen()) { - auto len = this->genConstantOffset(loc, rewriter, ty.getLen()); - return doCharacter(charWidth, len); - } - assert(!lenParams.empty()); - return doCharacter(charWidth, lenParams.back()); - } + if (auto ty = boxEleTy.dyn_cast()) + return doCharacter(ty, lenParams); // Logical type. if (auto ty = boxEleTy.dyn_cast()) - return doLogical(getKindMap().getLogicalBitsize(ty.getFKind())); + return doLogical(ty, getKindMap().getLogicalBitsize(ty.getFKind())); // Array types. if (auto seqTy = boxEleTy.dyn_cast()) return getSizeAndTypeCode(loc, rewriter, seqTy.getEleTy(), lenParams); // Derived-type types. if (boxEleTy.isa()) { - auto ptrTy = mlir::LLVM::LLVMPointerType::get( - this->lowerTy().convertType(boxEleTy)); - auto nullPtr = rewriter.create(loc, ptrTy); - auto gep = rewriter.create( - loc, ptrTy, nullPtr, llvm::ArrayRef{1}); - auto eleSize = rewriter.create( - loc, this->lowerTy().indexType(), gep); + auto eleSize = genTypeStrideInBytes(loc, i64Ty, rewriter, + this->convertType(boxEleTy)); return {eleSize, this->genConstantOffset(loc, rewriter, fir::derivedToTypeCode())}; } // Reference type. if (fir::isa_ref_type(boxEleTy)) { - // FIXME: use the target pointer size rather than sizeof(void*) - return {this->genConstantOffset(loc, rewriter, sizeof(void *)), - this->genConstantOffset(loc, rewriter, CFI_type_cptr)}; + auto ptrTy = mlir::LLVM::LLVMPointerType::get( + mlir::LLVM::LLVMVoidType::get(rewriter.getContext())); + mlir::Value size = genTypeStrideInBytes(loc, i64Ty, rewriter, ptrTy); + return {size, this->genConstantOffset(loc, rewriter, CFI_type_cptr)}; } fir::emitFatalError(loc, "unhandled type in fir.box code generation"); } @@ -1526,14 +1555,7 @@ // Adjust the element scaling factor if the element is a dependent type. if (fir::hasDynamicSize(seqEleTy)) { if (auto charTy = seqEleTy.dyn_cast()) { - assert(xbox.lenParams().size() == 1); - mlir::LLVM::ConstantOp charSize = genConstantIndex( - loc, i64Ty, rewriter, lowerTy().characterBitsize(charTy) / 8); - mlir::Value castedLen = - integerCast(loc, rewriter, i64Ty, operands[xbox.lenParamOffset()]); - auto byteOffset = - rewriter.create(loc, i64Ty, charSize, castedLen); - prevPtrOff = integerCast(loc, rewriter, i64Ty, byteOffset); + prevPtrOff = eleSize; } else if (seqEleTy.isa()) { // prevPtrOff = ; TODO(loc, "generate call to calculate size of PDT"); @@ -1546,14 +1568,14 @@ const auto hasSubcomp = !xbox.subcomponent().empty(); const bool hasSubstr = !xbox.substr().empty(); - /// Compute initial element stride that will be use to compute the step in - /// each dimension. - mlir::Value prevDimByteStride = integerCast(loc, rewriter, i64Ty, eleSize); + // Initial element stride that will be use to compute the step in + // each dimension. + mlir::Value prevDimByteStride = eleSize; if (hasSubcomp) { // We have a subcomponent. The step value needs to be the number of // bytes per element (which is a derived type). - auto eleTy = mlir::LLVM::LLVMPointerType::get(convertType(seqEleTy)); - prevDimByteStride = computeDerivedTypeSize(loc, eleTy, i64Ty, rewriter); + prevDimByteStride = + genTypeStrideInBytes(loc, i64Ty, rewriter, convertType(seqEleTy)); } else if (hasSubstr) { // We have a substring. The step value needs to be the number of bytes // per CHARACTER element. diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -19,14 +19,14 @@ } // CHECK-LABEL: define ptr @allocmem_scalar_nonchar( -// CHECK: call ptr @malloc(i64 4) +// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64)) func.func @allocmem_scalar_nonchar() -> !fir.heap { %1 = fir.allocmem i32 return %1 : !fir.heap } // CHECK-LABEL: define ptr @allocmem_scalars_nonchar( -// CHECK: call ptr @malloc(i64 400) +// CHECK: call ptr @malloc(i64 mul (i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i64 100)) func.func @allocmem_scalars_nonchar() -> !fir.heap { %0 = arith.constant 100 : index %1 = fir.allocmem i32, %0 @@ -82,7 +82,7 @@ // CHECK-LABEL: define ptr @allocmem_scalar_dynchar( // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 -// CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]] +// CHECK: %[[mul2:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[mul1]] // CHECK: call ptr @malloc(i64 %[[mul2]]) func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { %1 = fir.allocmem !fir.char<1,?>(%l : i32) @@ -92,7 +92,7 @@ // CHECK-LABEL: define ptr @allocmem_scalar_dynchar_kind( // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 -// CHECK: %[[mul2:.*]] = mul i64 2, %[[mul1]] +// CHECK: %[[mul2:.*]] = mul i64 ptrtoint (ptr getelementptr (i16, ptr null, i32 1) to i64), %[[mul1]] // CHECK: call ptr @malloc(i64 %[[mul2]]) func.func @allocmem_scalar_dynchar_kind(%l : i32) -> !fir.heap>{ %1 = fir.allocmem !fir.char<2,?>(%l : i32) @@ -147,7 +147,7 @@ // CHECK-LABEL: define ptr @allocmem_array_of_dynchar( // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 -// CHECK: %[[mul2:.*]] = mul i64 9, %[[mul1]] +// CHECK: %[[mul2:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), i64 9), %[[mul1]] // CHECK: call ptr @malloc(i64 %[[mul2]]) func.func @allocmem_array_of_dynchar(%l: i32) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%l : i32) @@ -184,7 +184,7 @@ // CHECK-LABEL: define ptr @allocmem_dynarray_of_nonchar2( // CHECK-SAME: i64 %[[extent:.*]]) -// CHECK: %[[prod1:.*]] = mul i64 4, %[[extent]] +// CHECK: %[[prod1:.*]] = mul i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), %[[extent]] // CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]] // CHECK: call ptr @malloc(i64 %[[prod2]]) func.func @allocmem_dynarray_of_nonchar2(%e: index) -> !fir.heap> { @@ -255,7 +255,7 @@ // CHECK-LABEL: define ptr @allocmem_dynarray_of_dynchar( // CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]]) // CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64 -// CHECK: %[[prod2:.*]] = mul i64 6, %[[prod1]] +// CHECK: %[[prod2:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr (i16, ptr null, i32 1) to i64), i64 3), %[[prod1]] // CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]] // CHECK: call ptr @malloc(i64 %[[prod3]]) func.func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap>> { @@ -266,7 +266,7 @@ // CHECK-LABEL: define ptr @allocmem_dynarray_of_dynchar2( // CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]]) // CHECK: %[[a:.*]] = sext i32 %[[len]] to i64 -// CHECK: %[[prod1:.*]] = mul i64 2, %[[a]] +// CHECK: %[[prod1:.*]] = mul i64 ptrtoint (ptr getelementptr (i16, ptr null, i32 1) to i64), %[[a]] // CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]] // CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]] // CHECK: call ptr @malloc(i64 %[[prod3]]) @@ -325,7 +325,7 @@ // CHECK-LABEL: define ptr @allocmem_array_with_holes_dynchar( // CHECK-SAME: i64 %[[len:.*]], i64 %[[extent:.*]]) -// CHECK: %[[a:.*]] = mul i64 24, %[[len]] +// CHECK: %[[a:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr (i16, ptr null, i32 1) to i64), i64 12), %[[len]] // CHECK: %[[b:.*]] = mul i64 %[[a]], %[[extent]] // CHECK: call ptr @malloc(i64 %[[b]]) func.func @allocmem_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.heap>> { diff --git a/flang/test/Fir/arrexp.fir b/flang/test/Fir/arrexp.fir --- a/flang/test/Fir/arrexp.fir +++ b/flang/test/Fir/arrexp.fir @@ -145,7 +145,7 @@ // CHECK: %[[EXT_GEP:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 7, i64 0, i32 1 // CHECK: %[[EXTENT:.*]] = load i64, ptr %[[EXT_GEP]] - // CHECK: %[[SIZE:.*]] = mul i64 4, %[[EXTENT]] + // CHECK: %[[SIZE:.*]] = mul i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), %[[EXTENT]] // CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SIZE]]) %1 = fir.slice %c2, %c10, %c1 : (index, index, index) -> !fir.slice<1> %2 = fir.array_load %arg0 [%1] : (!fir.box>, !fir.slice<1>) -> !fir.array diff --git a/flang/test/Fir/box.fir b/flang/test/Fir/box.fir --- a/flang/test/Fir/box.fir +++ b/flang/test/Fir/box.fir @@ -1,7 +1,7 @@ // RUN: tco -o - %s | FileCheck %s // Global box initialization (test must come first because llvm globals are emitted first). -// CHECK-LABEL: @globalx = internal global { ptr, i64, i32, i8, i8, i8, i8 } { ptr null, i64 4, i32 20180515, i8 0, i8 9, i8 2, i8 0 } +// CHECK-LABEL: @globalx = internal global { ptr, i64, i32, i8, i8, i8, i8 } { ptr null, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 9, i8 2, i8 0 } fir.global internal @globalx : !fir.box> { %c0 = arith.constant 0 : index %0 = fir.convert %c0 : (index) -> !fir.heap @@ -9,7 +9,7 @@ fir.has_value %1 : !fir.box> } -// CHECK-LABEL: @globaly = internal global { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr null, i64 4, i32 20180515, i8 1, i8 27, i8 2, i8 0,{{.*}}[3 x i64] [i64 1, i64 0, i64 4] +// CHECK-LABEL: @globaly = internal global { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr null, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 27, i8 2, i8 0,{{.*}}[3 x i64] [i64 1, i64 0, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64)] fir.global internal @globaly : !fir.box>> { %c0 = arith.constant 0 : index %0 = fir.convert %c0 : (index) -> !fir.heap> @@ -27,7 +27,7 @@ // CHECK: (ptr %[[ARG:.*]]) func.func @f(%a : !fir.ref) { // CHECK: %[[DESC:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8 } - // CHECK: %[[INS0:.*]] = insertvalue {{.*}} { ptr undef, i64 4, i32 20180515, i8 0, i8 27, i8 0, i8 0 }, ptr %[[ARG]], 0 + // CHECK: %[[INS0:.*]] = insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20180515, i8 0, i8 27, i8 0, i8 0 }, ptr %[[ARG]], 0 // CHECK: store {{.*}} %[[INS0]], {{.*}} %[[DESC]] %b = fir.embox %a : (!fir.ref) -> !fir.box @@ -44,7 +44,7 @@ %c1 = arith.constant 1 : index %c100 = arith.constant 100 : index %d = fir.shape %c100 : (index) -> !fir.shape<1> - // CHECK: %[[INS70:.*]] = insertvalue {{.*}} { ptr undef, i64 4, i32 20180515, i8 1, i8 27, i8 0, i8 0, {{.*}} }, ptr %{{.*}}, 0 + // CHECK: %[[INS70:.*]] = insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 27, i8 0, i8 0, {{.*}} }, ptr %{{.*}}, 0 %b = fir.embox %c(%d) : (!fir.ref>, !fir.shape<1>) -> !fir.box> // CHECK: call void @ga( fir.call @ga(%b) : (!fir.box>) -> () @@ -56,7 +56,8 @@ // CHECK-LABEL: define void @b1( // CHECK-SAME: ptr %[[res:.*]], ptr %[[arg0:.*]], i64 %[[arg1:.*]]) func.func @b1(%arg0 : !fir.ref>, %arg1 : index) -> !fir.box> { - // CHECK: insertvalue {{.*}} undef, i64 %[[arg1]], 1 + // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] + // CHECK: insertvalue {{.*}} undef, i64 %[[size]], 1 // CHECK: insertvalue {{.*}} i32 20180515, 2 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 %x = fir.embox %arg0 typeparams %arg1 : (!fir.ref>, index) -> !fir.box> @@ -70,8 +71,8 @@ // CHECK-SAME: ptr %[[arg0:.*]], i64 %[[arg1:.*]]) func.func @b2(%arg0 : !fir.ref>>, %arg1 : index) -> !fir.box>> { %1 = fir.shape %arg1 : (index) -> !fir.shape<1> - // CHECK: insertvalue {{.*}} { ptr undef, i64 5, i32 20180515, i8 1, i8 40, i8 0, i8 0, {{.*}} }, i64 %[[arg1]], 7, 0, 1 - // CHECK: insertvalue {{.*}} %{{.*}}, i64 5, 7, 0, 2 + // CHECK: insertvalue {{.*}} { ptr undef, i64 ptrtoint (ptr getelementptr ([5 x i8], ptr null, i32 1) to i64), i32 20180515, i8 1, i8 40, i8 0, i8 0, {{.*}} }, i64 %[[arg1]], 7, 0, 1 + // CHECK: insertvalue {{.*}} %{{.*}}, i64 ptrtoint (ptr getelementptr ([5 x i8], ptr null, i32 1) to i64), 7, 0, 2 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 %2 = fir.embox %arg0(%1) : (!fir.ref>>, !fir.shape<1>) -> !fir.box>> // CHECK: store {{.*}}, ptr %[[res]] @@ -83,10 +84,11 @@ // CHECK-SAME: ptr %[[res:.*]], ptr %[[arg0:.*]], i64 %[[arg1:.*]], i64 %[[arg2:.*]]) func.func @b3(%arg0 : !fir.ref>>, %arg1 : index, %arg2 : index) -> !fir.box>> { %1 = fir.shape %arg2 : (index) -> !fir.shape<1> - // CHECK: insertvalue {{.*}} i64 %[[arg1]], 1 + // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] + // CHECK: insertvalue {{.*}} i64 %[[size]], 1 // CHECK: insertvalue {{.*}} i32 20180515, 2 // CHECK: insertvalue {{.*}} i64 %[[arg2]], 7, 0, 1 - // CHECK: insertvalue {{.*}} i64 %[[arg1]], 7, 0, 2 + // CHECK: insertvalue {{.*}} i64 %[[size]], 7, 0, 2 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 %2 = fir.embox %arg0(%1) typeparams %arg1 : (!fir.ref>>, !fir.shape<1>, index) -> !fir.box>> // CHECK: store {{.*}}, ptr %[[res]] @@ -99,10 +101,11 @@ func.func @b4(%arg0 : !fir.ref>>, %arg1 : index) -> !fir.box>> { %c_7 = arith.constant 7 : index %1 = fir.shape %c_7 : (index) -> !fir.shape<1> - // CHECK: insertvalue {{.*}} i64 %[[arg1]], 1 + // CHECK: %[[size:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[arg1]] + // CHECK: insertvalue {{.*}} i64 %[[size]], 1 // CHECK: insertvalue {{.*}} i32 20180515, 2 // CHECK: insertvalue {{.*}} i64 7, 7, 0, 1 - // CHECK: insertvalue {{.*}} i64 %[[arg1]], 7, 0, 2 + // CHECK: insertvalue {{.*}} i64 %[[size]], 7, 0, 2 // CHECK: insertvalue {{.*}} ptr %[[arg0]], 0 %x = fir.embox %arg0(%1) typeparams %arg1 : (!fir.ref>>, !fir.shape<1>, index) -> !fir.box>> // CHECK: store {{.*}}, ptr %[[res]] @@ -144,12 +147,12 @@ // CHECK: %[[sdp2:.*]] = sdiv i64 %[[dp2]], 2 // CHECK: %[[cmp:.*]] = icmp sgt i64 %[[sdp2]], 0 // CHECK: %[[extent:.*]] = select i1 %[[cmp]], i64 %[[sdp2]], i64 0 - // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } { ptr undef, i64 4, i32 20180515, i8 2, i8 27, i8 0, i8 0, [2 x [3 x i64]] [{{\[}}3 x i64] [i64 1, i64 undef, i64 undef], [3 x i64] undef] }, i64 %[[extent]], 7, 0, 1 - // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 800, 7, 0, 2 + // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20180515, i8 2, i8 27, i8 0, i8 0, [2 x [3 x i64]] [{{\[}}3 x i64] [i64 1, i64 undef, i64 undef], [3 x i64] undef] }, i64 %[[extent]], 7, 0, 1 + // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 mul (i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i64 200), 7, 0, 2 // CHECK: %[[op25:.*]] = add i64 25000, %[[i100p40]] // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 1, 7, 1, 0 // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 4, 7, 1, 1 - // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 120000, 7, 1, 2 + // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, i64 mul (i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i64 30000), 7, 1, 2 // CHECK: %[[op300:.*]] = add i64 300000, %[[op25]] // CHECK: %[[ptr:.*]] = getelementptr float, ptr %[[ARG0]], i64 %[[op300]] // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } %{{.*}}, ptr %[[ptr]], 0 diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -198,8 +198,10 @@ } // CHECK-LABEL: llvm.func @test_alloc_and_freemem_one() { -// CHECK-NEXT: [[N:%.*]] = llvm.mlir.constant(4 : i64) : i64 -// CHECK-NEXT: llvm.call @malloc([[N]]) +// CHECK-NEXT: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK-NEXT: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK-NEXT: %[[N:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 +// CHECK-NEXT: llvm.call @malloc(%[[N]]) // CHECK: llvm.call @free(%{{.*}}) // CHECK-NEXT: llvm.return @@ -233,7 +235,9 @@ // CHECK-LABEL: llvm.func @test_with_shape // CHECK-SAME: %[[NCOLS:.*]]: i64, %[[NROWS:.*]]: i64 -// CHECK: %[[FOUR:.*]] = llvm.mlir.constant(4 : i64) : i64 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[FOUR:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]] : i64 // CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) @@ -251,7 +255,9 @@ // CHECK-LABEL: llvm.func @test_string_with_shape // CHECK-SAME: %[[LEN:.*]]: i64, %[[NELEMS:.*]]: i64) -// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[ONE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]] : i64 // CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) @@ -1502,9 +1508,10 @@ // CHECK: %[[C1:.*]] = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[C1]] x !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> {alignment = 8 : i64} : (i32) -> !llvm.ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})>> // CHECK: %[[DESC:.*]] = llvm.mlir.undef : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> -// CHECK: %[[ELEM_SIZE:.*]] = llvm.mlir.constant(4 : i32) : i32 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[I64_ELEM_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 -// CHECK: %[[I64_ELEM_SIZE:.*]] = llvm.sext %[[ELEM_SIZE]] : i32 to i64 // CHECK: %[[DESC0:.*]] = llvm.insertvalue %[[I64_ELEM_SIZE]], %[[DESC]][1] : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> // CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 // CHECK: %[[DESC1:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[DESC0]][2] : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}})> @@ -1724,9 +1731,10 @@ // CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[ALLOCA_SIZE]] x !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> {alignment = 8 : i64} : (i32) -> !llvm.ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)>> // CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> -// CHECK: %[[ELEM_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[TYPE:.*]] = llvm.mlir.constant(9 : i32) : i32 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 // CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> @@ -1743,7 +1751,6 @@ // CHECK: %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C0]], %[[C0]] : i64 // CHECK: %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]] : i64 // CHECK: %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]] : i64 @@ -1773,11 +1780,11 @@ // CHECK-LABEL: llvm.func @xembox1(%{{.*}}: !llvm.ptr>) { // CHECK: %[[C0:.*]] = llvm.mlir.constant(0 : i64) : i64 -// CHECK: %[[ELEM_LEN:.*]] = llvm.mlir.constant(10 : i32) : i32 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr> +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr> to i64 // CHECK: %{{.*}} = llvm.insertvalue %[[ELEM_LEN_I64]], %{{.*}}[1] : !llvm.struct<(ptr>, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> -// CHECK: %[[PTR_OFFSET:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 -// CHECK: %[[PREV_PTROFF:.*]] = llvm.mul %[[PTR_OFFSET]], %[[C0]] : i64 +// CHECK: %[[PREV_PTROFF:.*]] = llvm.mul %[[ELEM_LEN_I64]], %[[C0]] : i64 // Fortran realistic use case extracted from the following snippet: // @@ -1823,9 +1830,10 @@ // CHECK: %[[ARR_SIZE:.*]] = llvm.mul %[[ARR_SIZE_TMP1]], %[[N2]] : i64 // CHECK: %[[ARR:.*]] = llvm.alloca %[[ARR_SIZE]] x f64 {bindc_name = "arr", in_type = !fir.array, operand_segment_sizes = array, uniq_name = "_QFsbEarr"} : (i64) -> !llvm.ptr // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> -// CHECK: %[[ELEM_LEN:.*]] = llvm.mlir.constant(8 : i32) : i32 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(28 : i32) : i32 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 // CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> @@ -1842,7 +1850,6 @@ // CHECK: %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<2 x array<3 x i64>>)> // CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C2]], %[[SH1]] : i64 // CHECK: %[[DIM_OFFSET:.*]] = llvm.mul %[[ADJUSTED_OFFSET]], %[[ONE]] : i64 // CHECK: %[[PTR_OFFSET:.*]] = llvm.add %[[DIM_OFFSET]], %[[ZERO]] : i64 @@ -1902,9 +1909,10 @@ // CHECK: %[[ALLOCA_SIZE_X:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[X:.*]] = llvm.alloca %[[ALLOCA_SIZE_X]] x !llvm.array<20 x struct<"_QFtest_dt_sliceTt", (i32, i32)>> {bindc_name = "x", in_type = !fir.array<20x!fir.type<_QFtest_dt_sliceTt{i:i32,j:i32}>>, operand_segment_sizes = array, uniq_name = "_QFtest_dt_sliceEx"} : (i64) -> !llvm.ptr>> // CHECK: %[[BOX0:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> -// CHECK: %[[ELEM_LEN:.*]] = llvm.mlir.constant(4 : i32) : i32 +// CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 // CHECK: %[[TYPE_CODE:.*]] = llvm.mlir.constant(9 : i32) : i32 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[BOX1:.*]] = llvm.insertvalue %[[ELEM_LEN_I64]], %[[BOX0]][1] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 // CHECK: %[[BOX2:.*]] = llvm.insertvalue %[[VERSION]], %[[BOX1]][2] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> @@ -1921,11 +1929,10 @@ // CHECK: %[[BOX6:.*]] = llvm.insertvalue %[[F18ADDENDUM_I8]], %[[BOX5]][6] : !llvm.struct<(ptr, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, i{{.*}}, array<1 x array<3 x i64>>)> // CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 -// CHECK: %[[ELEM_LEN_I64:.*]] = llvm.sext %[[ELEM_LEN]] : i32 to i64 // CHECK: %[[ELE_TYPE:.*]] = llvm.mlir.null : !llvm.ptr> // CHECK: %[[GEP_DTYPE_SIZE:.*]] = llvm.getelementptr %[[ELE_TYPE]][1] : (!llvm.ptr>) -> !llvm.ptr> // CHECK: %[[PTRTOINT_DTYPE_SIZE:.*]] = llvm.ptrtoint %[[GEP_DTYPE_SIZE]] : !llvm.ptr> to i64 -// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %3, %30 : i64 +// CHECK: %[[ADJUSTED_OFFSET:.*]] = llvm.sub %[[C1]], %[[ONE]] : i64 // CHECK: %[[EXT_SUB:.*]] = llvm.sub %[[C10]], %[[C1]] : i64 // CHECK: %[[EXT_ADD:.*]] = llvm.add %[[EXT_SUB]], %[[C2]] : i64 // CHECK: %[[EXT_SDIV:.*]] = llvm.sdiv %[[EXT_ADD]], %[[C2]] : i64 @@ -2179,9 +2186,10 @@ //CHECK: %[[SIX:.*]] = llvm.mlir.constant(6 : index) : i64 //CHECK: %[[EIGHTY:.*]] = llvm.mlir.constant(80 : index) : i64 //CHECK: %[[RBOX:.*]] = llvm.mlir.undef : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> -//CHECK: %[[ELEM_SIZE:.*]] = llvm.mlir.constant(4 : i32) : i32 +//CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +//CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +//CHECK: %[[ELEM_SIZE_I64:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 //CHECK: %[[FLOAT_TYPE:.*]] = llvm.mlir.constant(27 : i32) : i32 -//CHECK: %[[ELEM_SIZE_I64:.*]] = llvm.sext %[[ELEM_SIZE]] : i32 to i64 //CHECK: %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE_I64]], %[[RBOX]][1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> //CHECK: %[[CFI_VERSION:.*]] = llvm.mlir.constant(20180515 : i32) : i32 //CHECK: %[[RBOX_TMP2:.*]] = llvm.insertvalue %[[CFI_VERSION]], %[[RBOX_TMP1]][2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> @@ -2251,8 +2259,12 @@ //CHECK: %[[RESULT_UB:.*]] = llvm.mlir.constant(60 : i64) : i64 //CHECK: %[[RESULT_STRIDE:.*]] = llvm.mlir.constant(9 : i64) : i64 //CHECK: %[[COMPONENT_OFFSET_1:.*]] = llvm.mlir.constant(1 : i64) : i64 -//CHECK: %[[ELEM_SIZE:.*]] = llvm.mlir.constant(7 : i64) : i64 +//CHECK: %[[ELEM_COUNT:.*]] = llvm.mlir.constant(7 : i64) : i64 //CHECK: %[[TYPE_CHAR:.*]] = llvm.mlir.constant(40 : i32) : i32 +//CHECK: %[[NULL:.*]] = llvm.mlir.null : !llvm.ptr +//CHECK: %[[GEP:.*]] = llvm.getelementptr %[[NULL]][1] +//CHECK: %[[CHAR_SIZE:.*]] = llvm.ptrtoint %[[GEP]] : !llvm.ptr to i64 +//CHECK: %[[ELEM_SIZE:.*]] = llvm.mul %[[CHAR_SIZE]], %[[ELEM_COUNT]] //CHECK: %[[RBOX_TMP1:.*]] = llvm.insertvalue %[[ELEM_SIZE]], %{{.*}}[1] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> //CHECK: %[[RBOX_TMP2:.*]] = llvm.insertvalue %{{.*}}, %[[RBOX_TMP1]][2] : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> //CHECK: %[[RANK:.*]] = llvm.mlir.constant(1 : i32) : i32 diff --git a/flang/test/Fir/embox.fir b/flang/test/Fir/embox.fir --- a/flang/test/Fir/embox.fir +++ b/flang/test/Fir/embox.fir @@ -13,8 +13,8 @@ // CHECK: %[[a2:.*]] = alloca [20 x i32], i64 1, align 4, // CHECK: %[[a3:.*]] = getelementptr [20 x i32], ptr %[[a2]], i64 0, i64 0, // CHECK: %[[a4:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } -// CHECK: { ptr undef, i64 4, i32 20180515, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] -// CHECK: [i64 1, i64 5, i64 8]] }, ptr %[[a3]], 0, +// CHECK: { ptr undef, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] +// CHECK: [i64 1, i64 5, i64 mul (i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i64 2)]] }, ptr %[[a3]], 0, // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[a4]], ptr %[[a1]], align 8 // CHECK: call void @_QPtest_callee(ptr %[[a1]]), %c20 = arith.constant 20 : index @@ -40,7 +40,7 @@ // CHECK: %[[a3:.*]] = alloca [20 x %_QFtest_dt_sliceTt], i64 1, align 8, // CHECK: %[[a4:.*]] = getelementptr [20 x %_QFtest_dt_sliceTt], ptr %[[a3]], i64 0, i64 0, i32 0, // CHECK: %[[a5:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } -// CHECK-SAME: { ptr undef, i64 4, i32 20180515, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] +// CHECK-SAME: { ptr undef, i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 9, i8 0, i8 0, [1 x [3 x i64]] // CHECK-SAME: [i64 1, i64 5, i64 mul // CHECK-SAME: (i64 ptrtoint (ptr getelementptr (%_QFtest_dt_sliceTt, ptr null, i32 1) to i64), i64 2)]] } // CHECK-SAME: , ptr %[[a4]], 0 @@ -75,7 +75,7 @@ %1 = fir.slice %c1, %c2, %c1, %c1, %c3, %c1 substr %c1_i64, %c2_i64 : (index, index, index, index, index, index, i64, i64) -> !fir.slice<2> %2 = fir.embox %arg0(%0) [%1] : (!fir.ref>>, !fir.shape<2>, !fir.slice<2>) -> !fir.box>> // CHECK: %[[addr:.*]] = getelementptr [3 x [2 x [4 x i8]]], ptr %[[arg0]], i64 0, i64 0, i64 0, i64 1 - // CHECK: insertvalue {[[descriptorType:.*]]} { ptr undef, i64 2, i32 20180515, i8 2, i8 40, i8 0, i8 0, + // CHECK: insertvalue {[[descriptorType:.*]]} { ptr undef, i64 mul (i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), i64 2), i32 20180515, i8 2, i8 40, i8 0, i8 0, // CHECK-SAME: [2 x [3 x i64]] [{{\[}}3 x i64] [i64 1, i64 2, i64 4], [3 x i64] [i64 1, i64 3, i64 8]] }, // CHECK-SAME: ptr %[[addr]], 0 @@ -98,7 +98,7 @@ // CHECK: %[[offset:.*]] = add i64 %[[mul]], 0 // CHECK: %[[addr:.*]] = getelementptr [40 x float], ptr %0, i64 %[[offset]], i64 0 // CHECK: %[[box:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } -// CHECK-SAME: { ptr undef, i64 4, i32 20180515, i8 1, i8 27, i8 0, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 40, i64 4]] }, ptr %[[addr]], 0 +// CHECK-SAME: { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 20180515, i8 1, i8 27, i8 0, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 40, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64)]] }, ptr %[[addr]], 0 %3 = fir.embox %arg0(%1) [%2] : (!fir.ref>, !fir.shapeshift<2>, !fir.slice<2>) -> !fir.box> fir.call @do_something(%3) : (!fir.box>) -> () return diff --git a/flang/test/Fir/rebox.fir b/flang/test/Fir/rebox.fir --- a/flang/test/Fir/rebox.fir +++ b/flang/test/Fir/rebox.fir @@ -33,7 +33,7 @@ // CHECK: %[[OFFSET_1:.*]] = mul i64 2, %[[INSTRIDE_1]] // CHECK: %[[VOIDBASE1:.*]] = getelementptr i8, ptr %[[VOIDBASE0]], i64 %[[OFFSET_1]] // CHECK: %[[OUTSTRIDE0:.*]] = mul i64 3, %[[INSTRIDE_1]] - // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr undef, i64 4, i32 {{.*}}, i8 1, i8 27, i8 0, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 25, i64 undef]] }, i64 %[[OUTSTRIDE0]], 7, 0, 2 + // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 {{.*}}, i8 1, i8 27, i8 0, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 25, i64 undef]] }, i64 %[[OUTSTRIDE0]], 7, 0, 2 // CHECK: %[[OUTBOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[OUTBOX0]], ptr %[[VOIDBASE1]], 0 // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[OUTBOX1]], ptr %[[OUTBOX_ALLOC]], align 8 %2 = fir.rebox %arg0(%1) [%0] : (!fir.box>, !fir.shift<2>, !fir.slice<2>) -> !fir.box> @@ -59,7 +59,8 @@ // CHECK: %[[OUTBOX:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } // CHECK: %[[LEN_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] }, ptr %[[INBOX]], i32 0, i32 1 // CHECK: %[[LEN:.*]] = load i64, ptr %[[LEN_GEP]] - // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } undef, i64 %[[LEN]], 1 + // CHECK: %[[SIZE:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[LEN]] + // CHECK: insertvalue { ptr, i64, i32, i8, i8, i8, i8, [2 x [3 x i64]] } undef, i64 %[[SIZE]], 1 %1 = fir.rebox %arg0 [%0] : (!fir.box>>, !fir.slice<2>) -> !fir.box>> fir.call @bar_rebox_test2(%1) : (!fir.box>>) -> () @@ -91,7 +92,7 @@ // CHECK: %[[INBASE:.*]] = load ptr, ptr %[[INBASE_GEP]] // CHECK: %[[OUTSTRIDE1:.*]] = mul i64 3, %[[INSTRIDE]] // CHECK: %[[OUTSTRIDE2:.*]] = mul i64 4, %[[OUTSTRIDE1]] - // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } { ptr undef, i64 4, i32 {{.*}}, i8 3, i8 27, i8 0, i8 0, [3 x [3 x i64]] [{{.*}} [i64 2, i64 3, i64 undef], [3 x i64] undef, [3 x i64] undef] }, i64 %[[INSTRIDE]], 7, 0, 2 + // CHECK: %[[OUTBOX0:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } { ptr undef, i64 ptrtoint (ptr getelementptr (float, ptr null, i32 1) to i64), i32 {{.*}}, i8 3, i8 27, i8 0, i8 0, [3 x [3 x i64]] [{{.*}} [i64 2, i64 3, i64 undef], [3 x i64] undef, [3 x i64] undef] }, i64 %[[INSTRIDE]], 7, 0, 2 // CHECK: %[[OUTBOX1:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX0]], i64 3, 7, 1, 0 // CHECK: %[[OUTBOX2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX1]], i64 4, 7, 1, 1 // CHECK: %[[OUTBOX3:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [3 x [3 x i64]] } %[[OUTBOX2]], i64 %[[OUTSTRIDE1]], 7, 1, 2 @@ -120,7 +121,7 @@ // CHECK: %[[STRIDE:.*]] = load i64, ptr %[[STRIDE_GEP]] // CHECK: %[[BASE_GEP:.*]] = getelementptr { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] }, ptr %[[INPUT]], i32 0, i32 0 // CHECK: %[[BASE:.*]] = load ptr, ptr %[[BASE_GEP]] - // CHECK: %[[NEWBOX1:.*]] = insertvalue {{{.*}}} { ptr undef, i64 10, i32 20180515, i8 1, i8 40, i8 1, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 undef, i64 undef]] }, i64 %[[EXTENT]], 7, 0, 1 + // CHECK: %[[NEWBOX1:.*]] = insertvalue {{{.*}}} { ptr undef, i64 ptrtoint (ptr getelementptr ([10 x i8], ptr null, i32 1) to i64), i32 20180515, i8 1, i8 40, i8 1, i8 0, [1 x [3 x i64]] [{{.*}} [i64 1, i64 undef, i64 undef]] }, i64 %[[EXTENT]], 7, 0, 1 // CHECK: %[[NEWBOX2:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX1]], i64 %[[STRIDE]], 7, 0, 2 // CHECK: %[[NEWBOX3:.*]] = insertvalue { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX2]], ptr %[[BASE]], 0 // CHECK: store { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]] } %[[NEWBOX3]], ptr %[[NEWBOX_STORAGE]] diff --git a/flang/test/Lower/forall/character-1.f90 b/flang/test/Lower/forall/character-1.f90 --- a/flang/test/Lower/forall/character-1.f90 +++ b/flang/test/Lower/forall/character-1.f90 @@ -23,7 +23,7 @@ ! CHECK: %[[extval:.*]] = load i64, ptr %[[extent]] ! CHECK: %[[elesize:.*]] = getelementptr { {{.*}}, [1 x [3 x i64]] }, ptr %[[arg]], i32 0, i32 1 ! CHECK: %[[esval:.*]] = load i64, ptr %[[elesize]] -! CHECK: %[[mul:.*]] = mul i64 1, %[[esval]] +! CHECK: %[[mul:.*]] = mul i64 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i64), %[[esval]] ! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]] ! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[mul2]]) ! CHECK: %[[to:.*]] = getelementptr i8, ptr %[[buff]], i64 %