[flang-commits] [flang] ac0f4c8 - [flang] Fix AllocaOp/AllocMemOp type conversion

via flang-commits flang-commits at lists.llvm.org
Fri May 6 07:11:34 PDT 2022


Author: PeixinQiao
Date: 2022-05-06T22:10:13+08:00
New Revision: ac0f4c8f362e819316ca152315e930f4e6515e9d

URL: https://github.com/llvm/llvm-project/commit/ac0f4c8f362e819316ca152315e930f4e6515e9d
DIFF: https://github.com/llvm/llvm-project/commit/ac0f4c8f362e819316ca152315e930f4e6515e9d.diff

LOG: [flang] Fix AllocaOp/AllocMemOp type conversion

For arrays without a constant interior or arrays of character with
dynamic length arrays, the data types are converted to a pointer to the
element type, so the scale size of the constant extents needs to be
counted. The previous AllocaOp conversion does not consider the arrays
of character with dynamic length arrays, and the previous AllocMemOp
conversion does not consider arrays without a constant interior. This
fixes them and refactors the code so that it can be shared. Also add
the test cases.

Reviewed By: Jean Perier

Differential Revision: https://reviews.llvm.org/D124766

Added: 
    

Modified: 
    flang/lib/Optimizer/CodeGen/CodeGen.cpp
    flang/test/Fir/alloc.fir
    flang/test/Fir/convert-to-llvm.fir

Removed: 
    


################################################################################
diff  --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index 2cc41382f0d17..edc0b33fa2d02 100644
--- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp
+++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
@@ -302,6 +302,33 @@ getDependentTypeMemSizeFn(fir::RecordType recTy, fir::AllocaOp op,
   return module.lookupSymbol<mlir::LLVM::LLVMFuncOp>(name);
 }
 
+// Compute the alloc scale size (constant factors encoded in the array type).
+// We do this for arrays without a constant interior or arrays of character with
+// dynamic length arrays, since those are the only ones that get decayed to a
+// pointer to the element type.
+template <typename OP>
+static mlir::Value
+genAllocationScaleSize(OP op, mlir::Type ity,
+                       mlir::ConversionPatternRewriter &rewriter) {
+  mlir::Location loc = op.getLoc();
+  mlir::Type dataTy = op.getInType();
+  mlir::Type scalarType = fir::unwrapSequenceType(dataTy);
+  auto seqTy = dataTy.dyn_cast<fir::SequenceType>();
+  if ((op.hasShapeOperands() && seqTy && !seqTy.hasConstantInterior()) ||
+      (seqTy && fir::characterWithDynamicLen(scalarType))) {
+    fir::SequenceType::Extent constSize = 1;
+    for (auto extent : seqTy.getShape())
+      if (extent != fir::SequenceType::getUnknownExtent())
+        constSize *= extent;
+    if (constSize != 1) {
+      mlir::Value constVal{
+          genConstantIndex(loc, ity, rewriter, constSize).getResult()};
+      return constVal;
+    }
+  }
+  return nullptr;
+}
+
 namespace {
 /// convert to LLVM IR dialect `alloca`
 struct AllocaOpConversion : public FIROpConversion<fir::AllocaOp> {
@@ -346,23 +373,9 @@ struct AllocaOpConversion : public FIROpConversion<fir::AllocaOp> {
                << scalarType << " with type parameters";
       }
     }
+    if (auto scaleSize = genAllocationScaleSize(alloc, ity, rewriter))
+      size = rewriter.create<mlir::LLVM::MulOp>(loc, ity, size, scaleSize);
     if (alloc.hasShapeOperands()) {
-      mlir::Type allocEleTy = fir::unwrapRefType(alloc.getType());
-      // Scale the size by constant factors encoded in the array type.
-      // We only do this for arrays that don't have a constant interior, since
-      // those are the only ones that get decayed to a pointer to the element
-      // type.
-      if (auto seqTy = allocEleTy.dyn_cast<fir::SequenceType>()) {
-        if (!seqTy.hasConstantInterior()) {
-          fir::SequenceType::Extent constSize = 1;
-          for (auto extent : seqTy.getShape())
-            if (extent != fir::SequenceType::getUnknownExtent())
-              constSize *= extent;
-          mlir::Value constVal{
-              genConstantIndex(loc, ity, rewriter, constSize).getResult()};
-          size = rewriter.create<mlir::LLVM::MulOp>(loc, ity, size, constVal);
-        }
-      }
       unsigned end = operands.size();
       for (; i < end; ++i)
         size = rewriter.create<mlir::LLVM::MulOp>(
@@ -1001,18 +1014,8 @@ struct AllocMemOpConversion : public FIROpConversion<fir::AllocMemOp> {
     if (fir::isRecordWithTypeParameters(fir::unwrapSequenceType(dataTy)))
       TODO(loc, "fir.allocmem codegen of derived type with length parameters");
     mlir::Value size = genTypeSizeInBytes(loc, ity, rewriter, ty);
-    // !fir.array<NxMx!fir.char<K,?>> sets `size` to the width of !fir.char<K>.
-    // So multiply the constant dimensions here.
-    if (fir::hasDynamicSize(dataTy))
-      if (auto seqTy = dataTy.dyn_cast<fir::SequenceType>())
-        if (fir::characterWithDynamicLen(seqTy.getEleTy())) {
-          fir::SequenceType::Extent arrSize = 1;
-          for (auto d : seqTy.getShape())
-            if (d != fir::SequenceType::getUnknownExtent())
-              arrSize *= d;
-          size = rewriter.create<mlir::LLVM::MulOp>(
-              loc, ity, size, genConstantIndex(loc, ity, rewriter, arrSize));
-        }
+    if (auto scaleSize = genAllocationScaleSize(heap, ity, rewriter))
+      size = rewriter.create<mlir::LLVM::MulOp>(loc, ity, size, scaleSize);
     for (mlir::Value opnd : adaptor.getOperands())
       size = rewriter.create<mlir::LLVM::MulOp>(
           loc, ity, size, integerCast(loc, rewriter, ity, opnd));

diff  --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir
index e18a888e803da..07c97ff0a7490 100644
--- a/flang/test/Fir/alloc.fir
+++ b/flang/test/Fir/alloc.fir
@@ -2,82 +2,333 @@
 
 // UNSUPPORTED: system-windows
 
-// CHECK-LABEL: define i32* @f1()
-func @f1() -> !fir.ref<i32> {
-  // CHECK: alloca i32, i64 1
+// CHECK-LABEL: define i32* @alloca_scalar_nonchar()
+// CHECK: alloca i32, i64 1
+func @alloca_scalar_nonchar() -> !fir.ref<i32> {
   %1 = fir.alloca i32
   return %1 : !fir.ref<i32>
 }
 
-// CHECK-LABEL: define i32* @f2()
-func @f2() -> !fir.ref<i32> {
+// CHECK-LABEL: define i32* @alloca_scalars_nonchar()
+// CHECK: alloca i32, i64 100
+func @alloca_scalars_nonchar() -> !fir.ref<i32> {
   %0 = arith.constant 100 : index
-  // CHECK: alloca i32, i64 100
   %1 = fir.alloca i32, %0
   return %1 : !fir.ref<i32>
 }
 
-// CHECK-LABEL: define i32* @f3()
-func @f3() -> !fir.heap<i32> {
-  // CHECK: call i8* @malloc(i64 4)
+// CHECK-LABEL: define i32* @allocmem_scalar_nonchar(
+// CHECK: call i8* @malloc(i64 4)
+func @allocmem_scalar_nonchar() -> !fir.heap<i32> {
   %1 = fir.allocmem i32
   return %1 : !fir.heap<i32>
 }
 
-// CHECK-LABEL: define i32* @f4()
-func @f4() -> !fir.heap<i32> {
+// CHECK-LABEL: define i32* @allocmem_scalars_nonchar(
+// CHECK: call i8* @malloc(i64 400)
+func @allocmem_scalars_nonchar() -> !fir.heap<i32> {
   %0 = arith.constant 100 : index
-  // CHECK: call i8* @malloc(i64 400)
   %1 = fir.allocmem i32, %0
   return %1 : !fir.heap<i32>
 }
 
-// CHECK-LABEL: define i32** @f5()
-func @f5() -> !fir.ref<!fir.ptr<!fir.array<?xi32>>> {
-  // CHECK: alloca i32*, i64 1
+// CHECK-LABEL: define [10 x i8]* @alloca_scalar_char(
+// CHECK: alloca [10 x i8], i64 1
+func @alloca_scalar_char() -> !fir.ref<!fir.char<1,10>> {
+  %1 = fir.alloca !fir.char<1,10>
+  return %1 : !fir.ref<!fir.char<1,10>>
+}
+
+// CHECK-LABEL: define [10 x i16]* @alloca_scalar_char_kind(
+// CHECK: alloca [10 x i16], i64 1
+func @alloca_scalar_char_kind() -> !fir.ref<!fir.char<2,10>> {
+  %1 = fir.alloca !fir.char<2,10>
+  return %1 : !fir.ref<!fir.char<2,10>>
+}
+
+// CHECK-LABEL: define [10 x i8]* @allocmem_scalar_char(
+// CHECK: call i8* @malloc(i64 ptrtoint ([10 x i8]* getelementptr ([10 x i8], [10 x i8]* null, i64 1) to i64))
+func @allocmem_scalar_char() -> !fir.heap<!fir.char<1,10>> {
+  %1 = fir.allocmem !fir.char<1,10>
+  return %1 : !fir.heap<!fir.char<1,10>>
+}
+
+// CHECK-LABEL: define [10 x i16]* @allocmem_scalar_char_kind(
+// CHECK: call i8* @malloc(i64 ptrtoint ([10 x i16]* getelementptr ([10 x i16], [10 x i16]* null, i64 1) to i64))
+func @allocmem_scalar_char_kind() -> !fir.heap<!fir.char<2,10>> {
+  %1 = fir.allocmem !fir.char<2,10>
+  return %1 : !fir.heap<!fir.char<2,10>>
+}
+
+// CHECK-LABEL: define i8* @alloca_scalar_dynchar(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: alloca i8, i64 %[[mul1]]
+func @alloca_scalar_dynchar(%l : i32) -> !fir.ref<!fir.char<1,?>> {
+  %1 = fir.alloca !fir.char<1,?>(%l : i32)
+  return %1 : !fir.ref<!fir.char<1,?>>
+}
+
+// CHECK-LABEL: define i16* @alloca_scalar_dynchar_kind(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: alloca i16, i64 %[[mul1]]
+func @alloca_scalar_dynchar_kind(%l : i32) -> !fir.ref<!fir.char<2,?>> {
+  %1 = fir.alloca !fir.char<2,?>(%l : i32)
+  return %1 : !fir.ref<!fir.char<2,?>>
+}
+
+// CHECK-LABEL: define i8* @allocmem_scalar_dynchar(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]]
+// CHECK: call i8* @malloc(i64 %[[mul2]])
+func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap<!fir.char<1,?>> {
+  %1 = fir.allocmem !fir.char<1,?>(%l : i32)
+  return %1 : !fir.heap<!fir.char<1,?>>
+}
+
+// CHECK-LABEL: define i16* @allocmem_scalar_dynchar_kind(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[mul2:.*]] = mul i64 2, %[[mul1]]
+// CHECK: call i8* @malloc(i64 %[[mul2]])
+func @allocmem_scalar_dynchar_kind(%l : i32) -> !fir.heap<!fir.char<2,?>>{
+  %1 = fir.allocmem !fir.char<2,?>(%l : i32)
+  return %1 : !fir.heap<!fir.char<2,?>>
+}
+
+// CHECK-LABEL: define i32** @alloca_ptr_to_dynarray_nonchar(
+// CHECK: %1 = alloca i32*, i64 1
+func @alloca_ptr_to_dynarray_nonchar() -> !fir.ref<!fir.ptr<!fir.array<?xi32>>> {
   %1 = fir.alloca !fir.ptr<!fir.array<?xi32>>
   return %1 : !fir.ref<!fir.ptr<!fir.array<?xi32>>>
 }
 
-// CHECK-LABEL: define i8* @char_array_alloca(
-// CHECK-SAME: i32 %[[l:.*]], i64 %[[e:.*]])
-func @char_array_alloca(%l: i32, %e : index) -> !fir.ref<!fir.array<?x?x!fir.char<1,?>>> {
-  // CHECK: %[[lcast:.*]] = sext i32 %[[l]] to i64
-  // CHECK: %[[prod:.*]] = mul i64 %[[lcast]], %[[e]]
-  // CHECK: %[[size:.*]] = mul i64 %[[prod]], %[[e]]
-  // CHECK: alloca i8, i64 %[[size]]
-  %a = fir.alloca !fir.array<?x?x!fir.char<1,?>>(%l : i32), %e, %e
-  return %a :  !fir.ref<!fir.array<?x?x!fir.char<1,?>>>
+// CHECK-LABEL: define [3 x [3 x i32]]* @alloca_array_of_nonchar(
+// CHECK: alloca [3 x [3 x i32]], i64 1
+func @alloca_array_of_nonchar() -> !fir.ref<!fir.array<3x3xi32>> {
+  %1 = fir.alloca !fir.array<3x3xi32>
+  return %1 : !fir.ref<!fir.array<3x3xi32>>
+}
+
+// CHECK-LABEL: define [3 x [3 x [10 x i8]]]* @alloca_array_of_char(
+// CHECK: alloca [3 x [3 x [10 x i8]]], i64 1
+func @alloca_array_of_char() -> !fir.ref<!fir.array<3x3x!fir.char<1,10>>> {
+  %1 = fir.alloca !fir.array<3x3x!fir.char<1,10>>
+  return %1 : !fir.ref<!fir.array<3x3x!fir.char<1,10>>>
+}
+
+// CHECK-LABEL: define i8* @alloca_array_of_dynchar(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[mul2:.*]] = mul i64 %[[mul1]], 9
+// CHECK: alloca i8, i64 %[[mul2]]
+func @alloca_array_of_dynchar(%l: i32) -> !fir.ref<!fir.array<3x3x!fir.char<1,?>>> {
+  %1 = fir.alloca !fir.array<3x3x!fir.char<1,?>>(%l : i32)
+  return %1 : !fir.ref<!fir.array<3x3x!fir.char<1,?>>>
+}
+
+// CHECK-LABEL: define [3 x [3 x i32]]* @allocmem_array_of_nonchar(
+// CHECK: call i8* @malloc(i64 ptrtoint ([3 x [3 x i32]]* getelementptr ([3 x [3 x i32]], [3 x [3 x i32]]* null, i64 1) to i64))
+func @allocmem_array_of_nonchar() -> !fir.heap<!fir.array<3x3xi32>> {
+  %1 = fir.allocmem !fir.array<3x3xi32>
+  return %1 : !fir.heap<!fir.array<3x3xi32>>
+}
+
+// CHECK-LABEL: define [3 x [3 x [10 x i8]]]* @allocmem_array_of_char(
+// CHECK: call i8* @malloc(i64 ptrtoint ([3 x [3 x [10 x i8]]]* getelementptr ([3 x [3 x [10 x i8]]], [3 x [3 x [10 x i8]]]* null, i64 1) to i64))
+func @allocmem_array_of_char() -> !fir.heap<!fir.array<3x3x!fir.char<1,10>>> {
+  %1 = fir.allocmem !fir.array<3x3x!fir.char<1,10>>
+  return %1 : !fir.heap<!fir.array<3x3x!fir.char<1,10>>>
+}
+
+// CHECK-LABEL: define i8* @allocmem_array_of_dynchar(
+// CHECK-SAME: i32 %[[len:.*]])
+// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[mul2:.*]] = mul i64 9, %[[mul1]]
+// CHECK: call i8* @malloc(i64 %[[mul2]])
+func @allocmem_array_of_dynchar(%l: i32) -> !fir.heap<!fir.array<3x3x!fir.char<1,?>>> {
+  %1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%l : i32)
+  return %1 : !fir.heap<!fir.array<3x3x!fir.char<1,?>>>
+}
+
+// CHECK-LABEL: define [3 x i32]* @alloca_dynarray_of_nonchar(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 1, %[[extent]]
+// CHECK: alloca [3 x i32], i64 %[[prod1]]
+func @alloca_dynarray_of_nonchar(%e: index) -> !fir.ref<!fir.array<3x?xi32>> {
+  %1 = fir.alloca !fir.array<3x?xi32>, %e
+  return %1 : !fir.ref<!fir.array<3x?xi32>>
+}
+
+// CHECK-LABEL: define i32* @alloca_dynarray_of_nonchar2(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 1, %[[extent]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: alloca i32, i64 %[[prod2]]
+func @alloca_dynarray_of_nonchar2(%e: index) -> !fir.ref<!fir.array<?x?xi32>> {
+  %1 = fir.alloca !fir.array<?x?xi32>, %e, %e
+  return %1 : !fir.ref<!fir.array<?x?xi32>>
 }
 
-// Constant factor of 60 (4*3*5) must be included.
-// CHECK-LABEL: define i32* @array_with_holes(
+// CHECK-LABEL: define [3 x i32]* @allocmem_dynarray_of_nonchar(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 ptrtoint ([3 x i32]* getelementptr ([3 x i32], [3 x i32]* null, i64 1) to i64), %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod1]])
+func @allocmem_dynarray_of_nonchar(%e: index) -> !fir.heap<!fir.array<3x?xi32>> {
+  %1 = fir.allocmem !fir.array<3x?xi32>, %e
+  return %1 : !fir.heap<!fir.array<3x?xi32>>
+}
+
+// CHECK-LABEL: define i32* @allocmem_dynarray_of_nonchar2(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 4, %[[extent]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod2]])
+func @allocmem_dynarray_of_nonchar2(%e: index) -> !fir.heap<!fir.array<?x?xi32>> {
+  %1 = fir.allocmem !fir.array<?x?xi32>, %e, %e
+  return %1 : !fir.heap<!fir.array<?x?xi32>>
+}
+
+// CHECK-LABEL: define [3 x [10 x i16]]* @alloca_dynarray_of_char(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 1, %[[extent]]
+// CHECK: alloca [3 x [10 x i16]], i64 %[[prod1]]
+func @alloca_dynarray_of_char(%e : index) -> !fir.ref<!fir.array<3x?x!fir.char<2,10>>> {
+  %1 = fir.alloca !fir.array<3x?x!fir.char<2,10>>, %e
+  return %1 : !fir.ref<!fir.array<3x?x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define [10 x i16]* @alloca_dynarray_of_char2(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 1, %[[extent]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: alloca [10 x i16], i64 %[[prod2]]
+func @alloca_dynarray_of_char2(%e : index) -> !fir.ref<!fir.array<?x?x!fir.char<2,10>>> {
+  %1 = fir.alloca !fir.array<?x?x!fir.char<2,10>>, %e, %e
+  return %1 : !fir.ref<!fir.array<?x?x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define [3 x [10 x i16]]* @allocmem_dynarray_of_char(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 ptrtoint ([3 x [10 x i16]]* getelementptr ([3 x [10 x i16]], [3 x [10 x i16]]* null, i64 1) to i64), %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod1]])
+func @allocmem_dynarray_of_char(%e : index) -> !fir.heap<!fir.array<3x?x!fir.char<2,10>>> {
+  %1 = fir.allocmem !fir.array<3x?x!fir.char<2,10>>, %e
+  return %1 : !fir.heap<!fir.array<3x?x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define [10 x i16]* @allocmem_dynarray_of_char2(
+// CHECK-SAME: i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = mul i64 ptrtoint ([10 x i16]* getelementptr ([10 x i16], [10 x i16]* null, i64 1) to i64), %[[extent]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod2]])
+func @allocmem_dynarray_of_char2(%e : index) -> !fir.heap<!fir.array<?x?x!fir.char<2,10>>> {
+  %1 = fir.allocmem !fir.array<?x?x!fir.char<2,10>>, %e, %e
+  return %1 : !fir.heap<!fir.array<?x?x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define i16* @alloca_dynarray_of_dynchar(
+// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], 3
+// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
+// CHECK: alloca i16, i64 %[[prod3]]
+func @alloca_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.ref<!fir.array<3x?x!fir.char<2,?>>> {
+  %1 = fir.alloca !fir.array<3x?x!fir.char<2,?>>(%l : i32), %e
+  return %1 : !fir.ref<!fir.array<3x?x!fir.char<2,?>>>
+}
+
+// CHECK-LABEL: define i16* @alloca_dynarray_of_dynchar2(
+// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
+// CHECK: alloca i16, i64 %[[prod3]]
+func @alloca_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.ref<!fir.array<?x?x!fir.char<2,?>>> {
+  %1 = fir.alloca !fir.array<?x?x!fir.char<2,?>>(%l : i32), %e, %e
+  return %1 : !fir.ref<!fir.array<?x?x!fir.char<2,?>>>
+}
+
+// CHECK-LABEL: define i16* @allocmem_dynarray_of_dynchar(
+// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
+// CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[prod2:.*]] = mul i64 6, %[[prod1]]
+// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod3]])
+func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap<!fir.array<3x?x!fir.char<2,?>>> {
+  %1 = fir.allocmem !fir.array<3x?x!fir.char<2,?>>(%l : i32), %e
+  return %1 : !fir.heap<!fir.array<3x?x!fir.char<2,?>>>
+}
+
+// CHECK-LABEL: define i16* @allocmem_dynarray_of_dynchar2(
+// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
+// CHECK: %[[a:.*]] = sext i32 %[[len]] to i64
+// CHECK: %[[prod1:.*]] = mul i64 2, %[[a]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
+// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
+// CHECK: call i8* @malloc(i64 %[[prod3]])
+func @allocmem_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.heap<!fir.array<?x?x!fir.char<2,?>>> {
+  %1 = fir.allocmem !fir.array<?x?x!fir.char<2,?>>(%l : i32), %e, %e
+  return %1 : !fir.heap<!fir.array<?x?x!fir.char<2,?>>>
+}
+
+// CHECK-LABEL: define i32* @alloca_array_with_holes_nonchar(
 // CHECK-SAME: i64 %[[a:.*]], i64 %[[b:.*]])
-func @array_with_holes(%0 : index, %1 : index) -> !fir.ref<!fir.array<4x?x3x?x5xi32>> {
-  // CHECK: %[[prod1:.*]] = mul i64 60, %[[a]]
-  // CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[b]]
-  // CHECK: alloca i32, i64 %[[prod2]]
+// CHECK: %[[prod1:.*]] = mul i64 60, %[[a]]
+// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[b]]
+// CHECK: alloca i32, i64 %[[prod2]]
+func @alloca_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.ref<!fir.array<4x?x3x?x5xi32>> {
   %a = fir.alloca !fir.array<4x?x3x?x5xi32>, %0, %1
   return %a : !fir.ref<!fir.array<4x?x3x?x5xi32>>
 }
 
-// CHECK-LABEL: define void @allocmem_array_of_dynchar(
-// CHECK-SAME: i64 %[[arg:.*]])
-// CHECK: %[[mul:.*]] = mul i64 9, %[[arg]]
-// CHECK: %[[malloc:.*]] = call i8* @malloc(i64 %[[mul]])
-// CHECK: ret void
-func @allocmem_array_of_dynchar(%arg0: index) {
-  %1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%arg0 : index)
-  return
+// CHECK-LABEL: define [10 x i16]* @alloca_array_with_holes_char(
+// CHECK-SAME: i64 %[[e:.*]])
+// CHECK: %[[mul:.*]] = mul i64 12, %[[e]]
+// CHECK: alloca [10 x i16], i64 %[[mul]]
+func @alloca_array_with_holes_char(%e: index) -> !fir.ref<!fir.array<3x?x4x!fir.char<2,10>>> {
+  %1 = fir.alloca !fir.array<3x?x4x!fir.char<2,10>>, %e
+  return %1 : !fir.ref<!fir.array<3x?x4x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define i16* @alloca_array_with_holes_dynchar(
+// CHECK-SAME: i64 %[[len:.*]], i64 %[[extent:.*]])
+// CHECK: %[[a:.*]] = mul i64 %[[len]], 12
+// CHECK: %[[b:.*]] = mul i64 %[[a]], %[[extent]]
+// CHECK: alloca i16, i64 %[[b]]
+func @alloca_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.ref<!fir.array<3x?x4x!fir.char<2,?>>> {
+  %1 = fir.alloca !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1
+  return %1 : !fir.ref<!fir.array<3x?x4x!fir.char<2,?>>>
+}
+
+// CHECK-LABEL: define i32* @allocmem_array_with_holes_nonchar(
+// CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]])
+// CHECK: %[[a:.*]] = mul i64 240, %[[e1]]
+// CHECK: %[[b:.*]] = mul i64 %3, %[[e2]]
+// CHECK: call i8* @malloc(i64 %[[b]])
+func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.heap<!fir.array<4x?x3x?x5xi32>> {
+  %a = fir.allocmem !fir.array<4x?x3x?x5xi32>, %0, %1
+  return %a : !fir.heap<!fir.array<4x?x3x?x5xi32>>
 }
 
-// CHECK-LABEL: define void @allocmem_dynarray_of_dynchar(
+// CHECK-LABEL: define [10 x i16]* @allocmem_array_with_holes_char(
+// CHECK-SAME: i64 %[[e:.*]])
+// CHECK: %[[mul:.*]] = mul i64 mul (i64 ptrtoint ([10 x i16]* getelementptr ([10 x i16], [10 x i16]* null, i64 1) to i64), i64 12), %[[e]]
+// CHECK: call i8* @malloc(i64 %[[mul]])
+func @allocmem_array_with_holes_char(%e: index) -> !fir.heap<!fir.array<3x?x4x!fir.char<2,10>>> {
+  %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,10>>, %e
+  return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,10>>>
+}
+
+// CHECK-LABEL: define i16* @allocmem_array_with_holes_dynchar(
 // CHECK-SAME: i64 %[[len:.*]], i64 %[[extent:.*]])
 // CHECK: %[[a:.*]] = mul i64 24, %[[len]]
 // CHECK: %[[b:.*]] = mul i64 %[[a]], %[[extent]]
-// CHECK: %[[malloc:.*]] = call i8* @malloc(i64 %[[b]])
-// CHECK: ret void
-func @allocmem_dynarray_of_dynchar(%arg0: index, %arg1: index) {
+// CHECK: call i8* @malloc(i64 %[[b]])
+func @allocmem_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>> {
   %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1
-  return
+  return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>>
 }
+

diff  --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir
index 81f38156081b5..d022c8a02884e 100644
--- a/flang/test/Fir/convert-to-llvm.fir
+++ b/flang/test/Fir/convert-to-llvm.fir
@@ -230,9 +230,7 @@ func @test_string_with_shape(%len: index, %nelems: index) {
 // CHECK-LABEL: llvm.func @test_string_with_shape
 // CHECK-SAME: %[[LEN:.*]]: i64, %[[NELEMS:.*]]: i64)
 // CHECK:   %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
-// CHECK:   %[[ONE2:.*]] = llvm.mlir.constant(1 : i64) : i64
-// CHECK:   %[[MUL1:.*]] = llvm.mul %[[ONE]], %[[ONE2]]  : i64
-// CHECK:   %[[LEN_SIZE:.*]] = llvm.mul %[[MUL1]], %[[LEN]]  : 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]])
 // CHECK:   %[[B1:.*]] = llvm.bitcast %[[MEM]] : !llvm.ptr<i8> to !llvm.ptr<i8>


        


More information about the flang-commits mailing list