-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Generate fir.pack/unpack_array in Lowering. #131704
Conversation
Depends on #131662 |
@llvm/pr-subscribers-flang-fir-hlfir Author: Slava Zakharin (vzakhari) ChangesBasic generation of array repacking operations in Lowering. Patch is 22.42 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131704.diff 5 Files Affected:
diff --git a/flang/include/flang/Lower/ConvertVariable.h b/flang/include/flang/Lower/ConvertVariable.h
index b9d7f89138032..293ffa010d14a 100644
--- a/flang/include/flang/Lower/ConvertVariable.h
+++ b/flang/include/flang/Lower/ConvertVariable.h
@@ -182,6 +182,22 @@ void genDeclareSymbol(Fortran::lower::AbstractConverter &converter,
/// track the cray pointee as Fortran pointer.
mlir::Type getCrayPointeeBoxType(mlir::Type);
+/// If the given array symbol must be repacked into contiguous
+/// memory, generate fir.pack_array for the given box array value.
+/// The returned extended value is a box with the same properties
+/// as the original.
+fir::ExtendedValue genPackArray(Fortran::lower::AbstractConverter &converter,
+ const Fortran::semantics::Symbol &sym,
+ fir::ExtendedValue exv);
+
+/// Given an operation defining the variable corresponding
+/// to the given symbol, generate fir.unpack_array operation
+/// that reverts the effect of fir.pack_array.
+/// \p def is expected to be hlfir.declare operation.
+void genUnpackArray(fir::FirOpBuilder &builder, mlir::Location loc,
+ fir::FortranVariableOpInterface def,
+ const Fortran::semantics::Symbol &sym);
+
} // namespace lower
} // namespace Fortran
#endif // FORTRAN_LOWER_CONVERT_VARIABLE_H
diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def
index 396c91948be36..6735bea551414 100644
--- a/flang/include/flang/Lower/LoweringOptions.def
+++ b/flang/include/flang/Lower/LoweringOptions.def
@@ -47,5 +47,20 @@ ENUM_LOWERINGOPT(ReallocateLHS, unsigned, 1, 1)
/// If true, initialize globals without initialization to zero.
/// On by default.
ENUM_LOWERINGOPT(InitGlobalZero, unsigned, 1, 1)
+
+/// If true, the arrays of unknown size and array temporaries
+/// are requested to be allocated in stack memory.
+ENUM_LOWERINGOPT(StackArrays, unsigned, 1, 0)
+
+/// If true, the dummy assumed shape arrays are conditionally
+/// packed into contiguous memory.
+ENUM_LOWERINGOPT(RepackArrays, unsigned, 1, 0)
+
+/// If true, the repacking (RepackArrays option above)
+/// will be done for arrays non-contiguous in any dimension,
+/// otherwise, it will be done only for arrays non-contiguous
+/// in the leading dimension.
+ENUM_LOWERINGOPT(RepackArraysWhole, unsigned, 1, 0)
+
#undef LOWERINGOPT
#undef ENUM_LOWERINGOPT
diff --git a/flang/lib/Lower/ConvertVariable.cpp b/flang/lib/Lower/ConvertVariable.cpp
index 05256fec67241..52e3578ae21f0 100644
--- a/flang/lib/Lower/ConvertVariable.cpp
+++ b/flang/lib/Lower/ConvertVariable.cpp
@@ -1009,6 +1009,17 @@ static void deallocateIntentOut(Fortran::lower::AbstractConverter &converter,
}
}
+static bool needsRepack(Fortran::lower::AbstractConverter &converter,
+ const Fortran::semantics::Symbol &sym) {
+ if (!converter.getLoweringOptions().getRepackArrays() ||
+ !converter.isRegisteredDummySymbol(sym) ||
+ !Fortran::semantics::IsAssumedShape(sym) ||
+ Fortran::evaluate::IsSimplyContiguous(sym, converter.getFoldingContext()))
+ return false;
+
+ return true;
+}
+
/// Instantiate a local variable. Precondition: Each variable will be visited
/// such that if its properties depend on other variables, the variables upon
/// which its properties depend will already have been visited.
@@ -1077,6 +1088,17 @@ static void instantiateLocal(Fortran::lower::AbstractConverter &converter,
loc, sym);
});
}
+ } else if (var.hasSymbol() && needsRepack(converter, var.getSymbol())) {
+ auto *builder = &converter.getFirOpBuilder();
+ mlir::Location loc = converter.getCurrentLocation();
+ auto *sym = &var.getSymbol();
+ std::optional<fir::FortranVariableOpInterface> varDef =
+ symMap.lookupVariableDefinition(*sym);
+ assert(varDef && "cannot find defining operation for an array that needs "
+ "to be repacked");
+ converter.getFctCtx().attachCleanup([builder, loc, varDef, sym]() {
+ Fortran::lower::genUnpackArray(*builder, loc, *varDef, *sym);
+ });
}
}
@@ -1914,10 +1936,13 @@ void Fortran::lower::genDeclareSymbol(
sym.GetUltimate());
auto name = converter.mangleName(sym);
mlir::Value dummyScope;
- if (converter.isRegisteredDummySymbol(sym))
+ fir::ExtendedValue base = exv;
+ if (converter.isRegisteredDummySymbol(sym)) {
+ base = genPackArray(converter, sym, exv);
dummyScope = converter.dummyArgsScopeValue();
+ }
hlfir::EntityWithAttributes declare = hlfir::genDeclare(
- loc, builder, exv, name, attributes, dummyScope, dataAttr);
+ loc, builder, base, name, attributes, dummyScope, dataAttr);
symMap.addVariableDefinition(sym, declare.getIfVariableInterface(), force);
return;
}
@@ -2562,3 +2587,75 @@ mlir::Type Fortran::lower::getCrayPointeeBoxType(mlir::Type fortranType) {
}
return fir::BoxType::get(fir::PointerType::get(baseType));
}
+
+fir::ExtendedValue
+Fortran::lower::genPackArray(Fortran::lower::AbstractConverter &converter,
+ const Fortran::semantics::Symbol &sym,
+ fir::ExtendedValue exv) {
+ if (!needsRepack(converter, sym))
+ return exv;
+
+ auto &opts = converter.getLoweringOptions();
+ llvm::SmallVector<mlir::Value> lenParams;
+ exv.match(
+ [&](const fir::CharArrayBoxValue &box) {
+ lenParams.emplace_back(box.getLen());
+ },
+ [&](const fir::BoxValue &box) {
+ lenParams.append(box.getExplicitParameters().begin(),
+ box.getExplicitParameters().end());
+ },
+ [](const auto &) {
+ llvm_unreachable("unexpected lowering for assumed-shape dummy");
+ });
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ const mlir::Location loc = genLocation(converter, sym);
+ bool stackAlloc = opts.getStackArrays();
+ // 1D arrays must always use 'whole' mode.
+ bool isInnermostMode = !opts.getRepackArraysWhole() && sym.Rank() > 1;
+ // Avoid copy-in for 'intent(out)' variables.
+ bool noCopy = Fortran::semantics::IsIntentOut(sym);
+ auto boxType = mlir::cast<fir::BaseBoxType>(fir::getBase(exv).getType());
+ mlir::Type elementType = boxType.unwrapInnerType();
+ llvm::SmallVector<mlir::Value> elidedLenParams =
+ fir::factory::elideLengthsAlreadyInType(elementType, lenParams);
+ auto packOp = builder.create<fir::PackArrayOp>(
+ loc, fir::getBase(exv), stackAlloc, isInnermostMode, noCopy,
+ /*max_size=*/mlir::IntegerAttr{},
+ /*max_element_size=*/mlir::IntegerAttr{},
+ /*min_stride=*/mlir::IntegerAttr{}, fir::PackArrayHeuristics::None,
+ elidedLenParams);
+
+ mlir::Value newBase = packOp.getResult();
+ return exv.match(
+ [&](const fir::CharArrayBoxValue &box) -> fir::ExtendedValue {
+ return box.clone(newBase);
+ },
+ [&](const fir::BoxValue &box) -> fir::ExtendedValue {
+ return box.clone(newBase);
+ },
+ [](const auto &) -> fir::ExtendedValue {
+ llvm_unreachable("unexpected lowering for assumed-shape dummy");
+ });
+}
+
+void Fortran::lower::genUnpackArray(fir::FirOpBuilder &builder,
+ mlir::Location loc,
+ fir::FortranVariableOpInterface def,
+ const Fortran::semantics::Symbol &sym) {
+ // Subtle: rely on the fact that the memref of the defining
+ // hlfir.declare is a result of fir.pack_array.
+ // Alternatively, we can track the pack operation for a symbol
+ // via SymMap.
+ auto declareOp = mlir::dyn_cast<hlfir::DeclareOp>(def.getOperation());
+ assert(declareOp &&
+ "cannot find hlfir.declare for an array that needs to be repacked");
+ auto packOp = declareOp.getMemref().getDefiningOp<fir::PackArrayOp>();
+ assert(packOp && "cannot find fir.pack_array");
+ mlir::Value temp = packOp.getResult();
+ mlir::Value original = packOp.getArray();
+ bool stackAlloc = packOp.getStack();
+ // Avoid copy-out for 'intent(in)' variables.
+ bool noCopy = Fortran::semantics::IsIntentIn(sym);
+ builder.create<fir::UnpackArrayOp>(loc, temp, original, stackAlloc, noCopy);
+}
diff --git a/flang/test/Lower/repack-arrays.f90 b/flang/test/Lower/repack-arrays.f90
new file mode 100644
index 0000000000000..19ea93a3521a3
--- /dev/null
+++ b/flang/test/Lower/repack-arrays.f90
@@ -0,0 +1,247 @@
+! RUN: bbc -emit-hlfir -frepack-arrays -fstack-arrays -frepack-arrays-continuity-whole %s -o - -I nowhere | FileCheck --check-prefixes=ALL,STACK,WHOLE %s
+! RUN: bbc -emit-hlfir -frepack-arrays -fstack-arrays=false -frepack-arrays-continuity-whole %s -o - -I nowhere | FileCheck --check-prefixes=ALL,HEAP,WHOLE %s
+! RUN: bbc -emit-hlfir -frepack-arrays -fstack-arrays -frepack-arrays-continuity-whole=false %s -o - -I nowhere | FileCheck --check-prefixes=ALL,STACK,INNER %s
+! RUN: bbc -emit-hlfir -frepack-arrays -fstack-arrays=false -frepack-arrays-continuity-whole=false %s -o - -I nowhere | FileCheck --check-prefixes=ALL,HEAP,INNER %s
+
+! ALL-LABEL: func.func @_QPtest1(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+subroutine test1(x)
+ real :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {uniq_name = "_QFtest1Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME: : !fir.box<!fir.array<?xf32>>
+end subroutine test1
+
+! ALL-LABEL: func.func @_QPtest2(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.ref<i32> {fir.bindc_name = "n"},
+! ALL-SAME: %[[VAL_1:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x?x!fir.char<1,?>>> {fir.bindc_name = "x"}) {
+subroutine test2(n, x)
+ integer :: n
+ character(n) :: x(:,:)
+! ALL: %[[VAL_8:.*]] = fir.pack_array %[[VAL_1]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! INNER-SAME: innermost
+! ALL-NOT: no_copy
+! ALL-SAME: typeparams %[[VAL_7:.*]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i32) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+! ALL: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_7]] dummy_scope %{{.*}} {uniq_name = "_QFtest2Ex"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, i32, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>)
+! ALL: fir.unpack_array %[[VAL_8]] to %[[VAL_1]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME: : !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+end subroutine test2
+
+! ALL-LABEL: func.func @_QPtest3(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>> {fir.bindc_name = "x"}) {
+subroutine test3(x)
+ type t
+ end type t
+ type(t) :: x(:,:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! INNER-SAME: innermost
+! ALL-NOT: no_copy
+! ALL-SAME: : (!fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>) -> !fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {uniq_name = "_QFtest3Ex"} : (!fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>, !fir.dscope) -> (!fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>, !fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME: : !fir.box<!fir.array<?x?x!fir.type<_QFtest3Tt>>>
+end subroutine test3
+
+! ALL-LABEL: func.func @_QPtest4(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+subroutine test4(x)
+ real, intent(inout) :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_inout>, uniq_name = "_QFtest4Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME : !fir.box<!fir.array<?xf32>>
+end subroutine test4
+
+! ALL-LABEL: func.func @_QPtest5(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+subroutine test5(x)
+ real, intent(in) :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME: (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest5Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-SAME no_copy : !fir.box<!fir.array<?xf32>>
+end subroutine test5
+
+! ALL-LABEL: func.func @_QPtest6(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+subroutine test6(x)
+ real, intent(out) :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-SAME no_copy : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<intent_out>, uniq_name = "_QFtest6Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME : !fir.box<!fir.array<?xf32>>
+end subroutine test6
+
+! ALL-LABEL: func.func @_QPtest7(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>> {fir.bindc_name = "x"}) {
+subroutine test7(x)
+ type t
+ end type t
+ class(t) :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME : (!fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>) -> !fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {uniq_name = "_QFtest7Ex"} : (!fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>, !fir.dscope) -> (!fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME : !fir.class<!fir.array<?x!fir.type<_QFtest7Tt>>>
+end subroutine test7
+
+! ALL-LABEL: func.func @_QPtest8(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) {
+subroutine test8(x)
+ real :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {uniq_name = "_QFtest8Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+ call inner(x(1))
+! ALL: fir.call @_QFtest8Pinner
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME : !fir.box<!fir.array<?xf32>>
+contains
+! ALL-LABEL: func.func private @_QFtest8Pinner(
+ subroutine inner(y)
+! ALL-NOT: fir.pack_array
+! ALL-NOT: fir.unpack_array
+ real :: y
+ y = 1.0
+ end subroutine inner
+end subroutine test8
+
+! ALL-LABEL: func.func @_QPtest9(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x"}) -> f32 {
+real function test9(x)
+ real :: x(:)
+! ALL: %[[VAL_6:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME : (!fir.box<!fir.array<?xf32>>) -> !fir.box<!fir.array<?xf32>>
+! ALL: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] dummy_scope %{{.*}} {uniq_name = "_QFtest9Ex"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
+ real :: y(10)
+ test9 = x(1)
+! ALL: fir.unpack_array %[[VAL_6]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME : !fir.box<!fir.array<?xf32>>
+! ALL-NEXT: return
+ return
+
+! ALL-LABEL: func.func @_QPtest9_alt(
+ entry test9_alt(y)
+! ALL-NOT: fir.pack_array
+! ALL-NOT: fir.unpack_array
+ rest9_ = y(1)
+end function test9
+
+! ALL-LABEL: func.func @_QPtest10(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x?xf32>> {fir.bindc_name = "x", fir.optional}) {
+subroutine test10(x)
+ real, optional :: x(:,:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! INNER-SAME: innermost
+! ALL-NOT: no_copy
+! ALL-SAME: : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+! ALL: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] dummy_scope %{{.*}} {fortran_attrs = #fir.var_attrs<optional>, uniq_name = "_QFtest10Ex"} : (!fir.box<!fir.array<?x?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>)
+! ALL: fir.unpack_array %[[VAL_2]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME: : !fir.box<!fir.array<?x?xf32>>
+end subroutine test10
+
+! ALL-LABEL: func.func @_QPtest11(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x!fir.char<1,10>>> {fir.bindc_name = "x"}) {
+subroutine test11(x)
+ character(10) :: x(:)
+! ALL: %[[VAL_3:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! INNER-SAME: whole
+! ALL-NOT: no_copy
+! ALL-SAME: : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<!fir.array<?x!fir.char<1,10>>>
+! ALL: fir.unpack_array %[[VAL_3]] to %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! ALL-NOT: no_copy
+! ALL-SAME: : !fir.box<!fir.array<?x!fir.char<1,10>>>
+end subroutine test11
+
+! ALL-LABEL: func.func @_QPtest12(
+! ALL-SAME: %[[VAL_0:[0-9]+|[a-zA-Z$._-][a-zA-Z0-9$._-]*]]: !fir.box<!fir.array<?x!fir.char<1,?>>> {fir.bindc_name = "x"}) {
+subroutine test12(x)
+ character(*) :: x(:)
+! ALL: %[[VAL_2:.*]] = fir.pack_array %[[VAL_0]]
+! STACK-SAME: stack
+! HEAP-SAME: heap
+! WHOLE-SAME: whole
+! INNER-SAME: whole
+! AL...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks Slava
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great
Basic generation of array repacking operations in Lowering.
f070204
to
00bd36c
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/35/builds/8321 Here is the relevant piece of the build log for the reference
|
Basic generation of array repacking operations in Lowering.