Files
clang-p2996/flang/test/Fir/alloc.fir
Vijay Kandiah c0cba51981 [Flang] Hoisting constant-sized allocas at flang codegen. (#95310)
This change modifies the `AllocaOpConversion` in flang codegen to insert
constant-sized LLVM allocas at the entry block of `LLVMFuncOp` or
OpenACC/OpenMP Op, rather than in-place at the `fir.alloca`. This
effectively hoists constant-sized FIR allocas to the proper block.

When compiling the example subroutine below with `flang-new`, we get a
llvm.stacksave/stackrestore pair around a constant-sized `fir.alloca
i32`.

```
subroutine test(n)
    block
      integer :: n
      print *, n
    end block
  end subroutine test
```

Without the proposed change, downstream LLVM compilation cannot hoist
this constant-sized alloca out of the stacksave/stackrestore region
which may lead to missed downstream optimizations:

```
*** IR Dump After Safe Stack instrumentation pass (safe-stack) ***
define void @test_(ptr %0) !dbg !3 {
  %2 = call ptr @llvm.stacksave.p0(), !dbg !7
  %3 = alloca i32, i64 1, align 4, !dbg !8
  %4 = call ptr @_FortranAioBeginExternalListOutput(i32 6, ptr @_QQclX62c91d05f046c7a656e7978eb13f2821, i32 4), !dbg !9
  %5 = load i32, ptr %3, align 4, !dbg !10, !tbaa !11
  %6 = call i1 @_FortranAioOutputInteger32(ptr %4, i32 %5), !dbg !10
  %7 = call i32 @_FortranAioEndIoStatement(ptr %4), !dbg !9
  call void @llvm.stackrestore.p0(ptr %2), !dbg !15
  ret void, !dbg !16
}
```

With this change, the `llvm.alloca` is already hoisted out of the
stacksave/stackrestore region during flang codegen:

```
// -----// IR Dump After FIRToLLVMLowering (fir-to-llvm-ir) //----- //
  llvm.func @test_(%arg0: !llvm.ptr {fir.bindc_name = "n"}) attributes {fir.internal_name = "_QPtest"} {
    %0 = llvm.mlir.constant(4 : i32) : i32
    %1 = llvm.mlir.constant(1 : i64) : i64
    %2 = llvm.alloca %1 x i32 {bindc_name = "n"} : (i64) -> !llvm.ptr
    %3 = llvm.mlir.constant(6 : i32) : i32
    %4 = llvm.mlir.undef : i1
    %5 = llvm.call @llvm.stacksave.p0() {fastmathFlags = #llvm.fastmath<contract>} : () -> !llvm.ptr
    %6 = llvm.mlir.addressof @_QQclX62c91d05f046c7a656e7978eb13f2821 : !llvm.ptr
    %7 = llvm.call @_FortranAioBeginExternalListOutput(%3, %6, %0) {fastmathFlags = #llvm.fastmath<contract>} : (i32, !llvm.ptr, i32) -> !llvm.ptr
    %8 = llvm.load %2 {tbaa = [#tbaa_tag]} : !llvm.ptr -> i32
    %9 = llvm.call @_FortranAioOutputInteger32(%7, %8) {fastmathFlags = #llvm.fastmath<contract>} : (!llvm.ptr, i32) -> i1
    %10 = llvm.call @_FortranAioEndIoStatement(%7) {fastmathFlags = #llvm.fastmath<contract>} : (!llvm.ptr) -> i32
    llvm.call @llvm.stackrestore.p0(%5) {fastmathFlags = #llvm.fastmath<contract>} : (!llvm.ptr) -> ()
    llvm.return
  }
```

---------

Co-authored-by: Vijay Kandiah <vkandiah@sky6.pgi.net>
2024-06-14 11:36:05 -05:00

352 lines
15 KiB
Plaintext

// RUN: tco %s | FileCheck %s
// RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck %s
// UNSUPPORTED: system-windows
// CHECK-LABEL: define ptr @alloca_scalar_nonchar()
// CHECK: alloca i32, i64 1
func.func @alloca_scalar_nonchar() -> !fir.ref<i32> {
%1 = fir.alloca i32
return %1 : !fir.ref<i32>
}
// CHECK-LABEL: define ptr @alloca_scalars_nonchar()
// CHECK: alloca i32, i64 100
func.func @alloca_scalars_nonchar() -> !fir.ref<i32> {
%0 = arith.constant 100 : index
%1 = fir.alloca i32, %0
return %1 : !fir.ref<i32>
}
// CHECK-LABEL: define ptr @allocmem_scalar_nonchar(
// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64))
func.func @allocmem_scalar_nonchar() -> !fir.heap<i32> {
%1 = fir.allocmem i32
return %1 : !fir.heap<i32>
}
// CHECK-LABEL: define ptr @allocmem_scalars_nonchar(
// 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<i32> {
%0 = arith.constant 100 : index
%1 = fir.allocmem i32, %0
return %1 : !fir.heap<i32>
}
// CHECK-LABEL: define ptr @alloca_scalar_char(
// CHECK: alloca [10 x i8], i64 1
func.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 ptr @alloca_scalar_char_kind(
// CHECK: alloca [10 x i16], i64 1
func.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 ptr @allocmem_scalar_char(
// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr ([10 x i8], ptr null, i32 1) to i64))
func.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 ptr @allocmem_scalar_char_kind(
// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr ([10 x i16], ptr null, i32 1) to i64))
func.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 ptr @alloca_scalar_dynchar(
// CHECK-SAME: i32 %[[len:.*]])
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
// CHECK: alloca i8, i64 %[[mul1]]
func.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 ptr @alloca_scalar_dynchar_kind(
// CHECK-SAME: i32 %[[len:.*]])
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
// CHECK: alloca i16, i64 %[[mul1]]
func.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 ptr @allocmem_scalar_dynchar(
// CHECK-SAME: i32 %[[len:.*]])
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
// 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<!fir.char<1,?>> {
%1 = fir.allocmem !fir.char<1,?>(%l : i32)
return %1 : !fir.heap<!fir.char<1,?>>
}
// CHECK-LABEL: define ptr @allocmem_scalar_dynchar_kind(
// CHECK-SAME: i32 %[[len:.*]])
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
// 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<!fir.char<2,?>>{
%1 = fir.allocmem !fir.char<2,?>(%l : i32)
return %1 : !fir.heap<!fir.char<2,?>>
}
// CHECK-LABEL: define ptr @alloca_ptr_to_dynarray_nonchar(
// CHECK: %1 = alloca ptr, i64 1
func.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 ptr @alloca_array_of_nonchar(
// CHECK: alloca [3 x [3 x i32]], i64 1
func.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 ptr @alloca_array_of_char(
// CHECK: alloca [3 x [3 x [10 x i8]]], i64 1
func.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 ptr @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.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 ptr @allocmem_array_of_nonchar(
// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr ([3 x [3 x i32]], ptr null, i32 1) to i64))
func.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 ptr @allocmem_array_of_char(
// CHECK: call ptr @malloc(i64 ptrtoint (ptr getelementptr ([3 x [3 x [10 x i8]]], ptr null, i32 1) to i64))
func.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 ptr @allocmem_array_of_dynchar(
// CHECK-SAME: i32 %[[len:.*]])
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
// 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<!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 ptr @alloca_dynarray_of_nonchar(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 %[[extent]], 1
// CHECK: alloca [3 x i32], i64 %[[prod1]]
func.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 ptr @alloca_dynarray_of_nonchar2(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 %[[extent]], 1
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
// CHECK: alloca i32, i64 %[[prod2]]
func.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>>
}
// CHECK-LABEL: define ptr @allocmem_dynarray_of_nonchar(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 ptrtoint (ptr getelementptr ([3 x i32], ptr null, i32 1) to i64), %[[extent]]
// CHECK: call ptr @malloc(i64 %[[prod1]])
func.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 ptr @allocmem_dynarray_of_nonchar2(
// CHECK-SAME: i64 %[[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<!fir.array<?x?xi32>> {
%1 = fir.allocmem !fir.array<?x?xi32>, %e, %e
return %1 : !fir.heap<!fir.array<?x?xi32>>
}
// CHECK-LABEL: define ptr @alloca_dynarray_of_char(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 %[[extent]], 1
// CHECK: alloca [3 x [10 x i16]], i64 %[[prod1]]
func.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 ptr @alloca_dynarray_of_char2(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 %[[extent]], 1
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
// CHECK: alloca [10 x i16], i64 %[[prod2]]
func.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 ptr @allocmem_dynarray_of_char(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 ptrtoint (ptr getelementptr ([3 x [10 x i16]], ptr null, i32 1) to i64), %[[extent]]
// CHECK: call ptr @malloc(i64 %[[prod1]])
func.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 ptr @allocmem_dynarray_of_char2(
// CHECK-SAME: i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = mul i64 ptrtoint (ptr getelementptr ([10 x i16], ptr null, i32 1) to i64), %[[extent]]
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
// CHECK: call ptr @malloc(i64 %[[prod2]])
func.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 ptr @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.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 ptr @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.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 ptr @allocmem_dynarray_of_dynchar(
// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
// CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64
// 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<!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 ptr @allocmem_dynarray_of_dynchar2(
// CHECK-SAME: i32 %[[len:.*]], i64 %[[extent:.*]])
// CHECK: %[[a:.*]] = sext i32 %[[len]] to i64
// 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]])
func.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 ptr @alloca_array_with_holes_nonchar(
// CHECK-SAME: i64 %[[a:.*]], i64 %[[b:.*]])
// CHECK: %[[prod1:.*]] = mul i64 15, %[[a]]
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[b]]
// CHECK: alloca [4 x i32], i64 %[[prod2]]
func.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 ptr @alloca_array_with_holes_char(
// CHECK-SAME: i64 %[[e:.*]])
// CHECK: %[[mul:.*]] = mul i64 4, %[[e]]
// CHECK: alloca [3 x [10 x i16]], i64 %[[mul]]
func.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 ptr @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.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 ptr @allocmem_array_with_holes_nonchar(
// CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]])
// CHECK: %[[a:.*]] = mul i64 mul (i64 ptrtoint{{.*}} 15), %[[e1]]
// CHECK: %[[b:.*]] = mul i64 %3, %[[e2]]
// CHECK: call ptr @malloc(i64 %[[b]])
func.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 ptr @allocmem_array_with_holes_char(
// CHECK-SAME: i64 %[[e:.*]])
// CHECK: %[[mul:.*]] = mul i64 mul (i64 ptrtoint (ptr getelementptr ([3 x [10 x i16]], ptr null, i32 1) to i64), i64 4), %[[e]]
// CHECK: call ptr @malloc(i64 %[[mul]])
func.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 ptr @allocmem_array_with_holes_dynchar(
// CHECK-SAME: i64 %[[len:.*]], i64 %[[extent:.*]])
// 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<!fir.array<3x?x4x!fir.char<2,?>>> {
%1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1
return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>>
}
// CHECK-LABEL: define void @alloca_unlimited_polymorphic_box
// CHECK: %[[VAL_1:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, i64 1
// CHECK: %[[VAL_0:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
// CHECK: %[[VAL_3:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, [1 x [3 x i64]], ptr, [1 x i64] }, i64 1
// CHECK: %[[VAL_2:.*]] = alloca { ptr, i64, i32, i8, i8, i8, i8, ptr, [1 x i64] }, i64 1
func.func @alloca_unlimited_polymorphic_box() {
%0 = fir.alloca !fir.class<none>
%1 = fir.alloca !fir.class<!fir.array<?xnone>>
%2 = fir.alloca !fir.box<none>
%3 = fir.alloca !fir.box<!fir.array<?xnone>>
return
}
// Note: allocmem of fir.box are not possible (fir::HeapType::verify does not
// accept box types), so there is no equivalent of
// alloca_unlimited_polymorphic_box for allocmem.