[flang-commits] [flang] af2e597 - [flang] enable as_expr codegen from array without FortranVariabeInterface
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Fri Dec 16 00:24:36 PST 2022
Author: Jean Perier
Date: 2022-12-16T09:22:24+01:00
New Revision: af2e5975222c4df3567d7cafcd5e1bd8fe7b86bd
URL: https://github.com/llvm/llvm-project/commit/af2e5975222c4df3567d7cafcd5e1bd8fe7b86bd
DIFF: https://github.com/llvm/llvm-project/commit/af2e5975222c4df3567d7cafcd5e1bd8fe7b86bd.diff
LOG: [flang] enable as_expr codegen from array without FortranVariabeInterface
The defining op of HLFIR variables is expected to be visible
in most cases, but HLFIR codegen won't rely on it from a correctness
point of view.
This patch allows building a fir.shape from an hlfir::Entity does not
have a visible FortranVariabeInterface defining op.
Differential Revision: https://reviews.llvm.org/D140099
Added:
Modified:
flang/include/flang/Optimizer/Dialect/FIROps.td
flang/lib/Optimizer/Builder/HLFIRTools.cpp
flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
flang/test/HLFIR/as_expr-codegen.fir
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 088294cf264ae..cbe5940f07e68 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -1029,6 +1029,9 @@ def fir_BoxDimsOp : fir_Op<"box_dims", [NoMemoryEffect]> {
let extraClassDeclaration = [{
mlir::Type getTupleType();
+ mlir::Value getLowerBound() {return getResult(0);};
+ mlir::Value getExtent() {return getResult(1);};
+ mlir::Value getByteStride() {return getResult(2);};
}];
}
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index faba6e1e9fc24..cdb78bd886696 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -358,6 +358,12 @@ mlir::Value hlfir::genShape(mlir::Location loc, fir::FirOpBuilder &builder,
else
entity = followEntitySource(entity);
+ if (entity.getType().isa<hlfir::ExprType>()) {
+ if (auto elemental = entity.getDefiningOp<hlfir::ElementalOp>())
+ return elemental.getShape();
+ TODO(loc, "get shape from HLFIR expr without producer holding the shape");
+ }
+ // Entity is an array variable.
if (auto varIface = entity.getIfVariableInterface()) {
if (auto shape = varIface.getShape()) {
if (shape.getType().isa<fir::ShapeType>())
@@ -366,12 +372,28 @@ mlir::Value hlfir::genShape(mlir::Location loc, fir::FirOpBuilder &builder,
if (auto s = shape.getDefiningOp<fir::ShapeShiftOp>())
return builder.create<fir::ShapeOp>(loc, s.getExtents());
}
- } else if (entity.getType().isa<hlfir::ExprType>()) {
- if (auto elemental = entity.getDefiningOp<hlfir::ElementalOp>())
- return elemental.getShape();
- TODO(loc, "get shape from HLFIR expr without producer holding the shape");
}
- TODO(loc, "get shape from HLFIR variable without interface");
+ // There is no shape lying around for this entity: build one using
+ // the type shape information, and/or the fir.box/fir.class shape
+ // information if any extents are not static.
+ fir::SequenceType seqTy =
+ hlfir::getFortranElementOrSequenceType(entity.getType())
+ .cast<fir::SequenceType>();
+ llvm::SmallVector<mlir::Value> extents;
+ mlir::Type idxTy = builder.getIndexType();
+ for (auto typeExtent : seqTy.getShape())
+ if (typeExtent != fir::SequenceType::getUnknownExtent()) {
+ extents.push_back(builder.createIntegerConstant(loc, idxTy, typeExtent));
+ } else {
+ assert(entity.getType().isa<fir::BaseBoxType>() &&
+ "array variable with dynamic extent must be boxes");
+ mlir::Value dim =
+ builder.createIntegerConstant(loc, idxTy, extents.size());
+ auto dimInfo =
+ builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, entity, dim);
+ extents.push_back(dimInfo.getExtent());
+ }
+ return builder.create<fir::ShapeOp>(loc, extents);
}
void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
index 728c1ddf64ab5..4a35b73113112 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
@@ -118,19 +118,28 @@ getIndexExtents(mlir::Location loc, fir::FirOpBuilder &builder,
static std::pair<hlfir::Entity, mlir::Value>
createTempFromMold(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::Entity mold) {
- if (mold.isArray())
- TODO(loc, "create temps from array mold");
llvm::SmallVector<mlir::Value> lenParams;
hlfir::genLengthParameters(loc, builder, mold, lenParams);
llvm::StringRef tmpName{".tmp"};
- mlir::Value alloca =
- builder.createTemporary(loc, mold.getFortranElementType(), tmpName,
- /*shape*/ std::nullopt, lenParams);
+ mlir::Value alloc;
+ mlir::Value isHeapAlloc;
+ mlir::Value shape{};
+ if (mold.isArray()) {
+ mlir::Type sequenceType =
+ hlfir::getFortranElementOrSequenceType(mold.getType());
+ shape = hlfir::genShape(loc, builder, mold);
+ auto extents = getIndexExtents(loc, builder, shape);
+ alloc = builder.createHeapTemporary(loc, sequenceType, tmpName, extents,
+ lenParams);
+ isHeapAlloc = builder.createBool(loc, true);
+ } else {
+ alloc = builder.createTemporary(loc, mold.getFortranElementType(), tmpName,
+ /*shape*/ std::nullopt, lenParams);
+ isHeapAlloc = builder.createBool(loc, false);
+ }
auto declareOp = builder.create<hlfir::DeclareOp>(
- loc, alloca, tmpName, /*shapeOrShift*/ mlir::Value{}, lenParams,
- fir::FortranVariableFlagsAttr{});
- mlir::Value falseVal = builder.createBool(loc, false);
- return {hlfir::Entity{declareOp.getBase()}, falseVal};
+ loc, alloc, tmpName, shape, lenParams, fir::FortranVariableFlagsAttr{});
+ return {hlfir::Entity{declareOp.getBase()}, isHeapAlloc};
}
static std::pair<hlfir::Entity, mlir::Value>
diff --git a/flang/test/HLFIR/as_expr-codegen.fir b/flang/test/HLFIR/as_expr-codegen.fir
index 077b5dae32e6e..7f7c310952477 100644
--- a/flang/test/HLFIR/as_expr-codegen.fir
+++ b/flang/test/HLFIR/as_expr-codegen.fir
@@ -12,8 +12,8 @@ func.func @char_expr(%addr: !fir.ref<!fir.char<1,?>>, %len: index) {
// CHECK-SAME: %[[VAL_1:.*]]: index) {
// CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "c"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
// CHECK: %[[VAL_3:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_1]] : index) {bindc_name = ".tmp"}
-// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
// CHECK: %[[VAL_5:.*]] = arith.constant false
+// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
// CHECK: hlfir.assign %[[VAL_2]]#0 to %[[VAL_4]]#0 : !fir.boxchar<1>, !fir.boxchar<1>
// CHECK: %[[VAL_6:.*]] = fir.undefined tuple<!fir.boxchar<1>, i1>
// CHECK: %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_5]], [1 : index] : (tuple<!fir.boxchar<1>, i1>, i1) -> tuple<!fir.boxchar<1>, i1>
@@ -29,9 +29,45 @@ func.func @char_expr_2(%addr: !fir.ref<!fir.char<1,10>>, %len: index) {
// CHECK-SAME: %[[VAL_1:.*]]: index) {
// CHECK: %[[VAL_2:.*]] = fir.alloca !fir.char<1,10> {bindc_name = ".tmp"}
// CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "c"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>)
-// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>)
// CHECK: %[[VAL_5:.*]] = arith.constant false
+// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>)
// CHECK: hlfir.assign %[[VAL_3]]#0 to %[[VAL_4]]#0 : !fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>
// CHECK: %[[VAL_6:.*]] = fir.undefined tuple<!fir.ref<!fir.char<1,10>>, i1>
// CHECK: %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_5]], [1 : index] : (tuple<!fir.ref<!fir.char<1,10>>, i1>, i1) -> tuple<!fir.ref<!fir.char<1,10>>, i1>
// CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_4]]#0, [0 : index] : (tuple<!fir.ref<!fir.char<1,10>>, i1>, !fir.ref<!fir.char<1,10>>) -> tuple<!fir.ref<!fir.char<1,10>>, i1>
+
+func.func @shape_from_type(%arg0 : !fir.ref<!fir.array<10x20xi32>>) {
+ %expr = hlfir.as_expr %arg0 : (!fir.ref<!fir.array<10x20xi32>>) -> !hlfir.expr<10x20xi32>
+ return
+}
+// CHECK-LABEL: func.func @shape_from_type(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.array<10x20xi32>>) {
+// CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 20 : index
+// CHECK: %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
+// CHECK: %[[VAL_4:.*]] = fir.allocmem !fir.array<10x20xi32> {bindc_name = ".tmp", uniq_name = ""}
+// CHECK: %[[VAL_5:.*]] = arith.constant true
+// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_3]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<10x20xi32>>, !fir.shape<2>) -> (!fir.heap<!fir.array<10x20xi32>>, !fir.heap<!fir.array<10x20xi32>>)
+// CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_6]]#0 : !fir.ref<!fir.array<10x20xi32>>, !fir.heap<!fir.array<10x20xi32>>
+// CHECK: %[[VAL_7:.*]] = fir.undefined tuple<!fir.heap<!fir.array<10x20xi32>>, i1>
+// CHECK: %[[VAL_8:.*]] = fir.insert_value %[[VAL_7]], %[[VAL_5]], [1 : index] : (tuple<!fir.heap<!fir.array<10x20xi32>>, i1>, i1) -> tuple<!fir.heap<!fir.array<10x20xi32>>, i1>
+// CHECK: %[[VAL_9:.*]] = fir.insert_value %[[VAL_8]], %[[VAL_6]]#0, [0 : index] : (tuple<!fir.heap<!fir.array<10x20xi32>>, i1>, !fir.heap<!fir.array<10x20xi32>>) -> tuple<!fir.heap<!fir.array<10x20xi32>>, i1>
+
+
+func.func @shape_from_box(%arg0 : !fir.class<!fir.array<10x?xi32>>) {
+ %expr = hlfir.as_expr %arg0 : (!fir.class<!fir.array<10x?xi32>>) -> !hlfir.expr<10x?xi32>
+ return
+}
+// CHECK-LABEL: func.func @shape_from_box(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.class<!fir.array<10x?xi32>>) {
+// CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
+// CHECK: %[[VAL_2:.*]] = arith.constant 1 : index
+// CHECK: %[[VAL_3:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_2]] : (!fir.class<!fir.array<10x?xi32>>, index) -> (index, index, index)
+// CHECK: %[[VAL_4:.*]] = fir.shape %[[VAL_1]], %[[VAL_3]]#1 : (index, index) -> !fir.shape<2>
+// CHECK: %[[VAL_5:.*]] = fir.allocmem !fir.array<10x?xi32>, %[[VAL_3]]#1 {bindc_name = ".tmp", uniq_name = ""}
+// CHECK: %[[VAL_6:.*]] = arith.constant true
+// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_5]](%[[VAL_4]]) {uniq_name = ".tmp"} : (!fir.heap<!fir.array<10x?xi32>>, !fir.shape<2>) -> (!fir.box<!fir.array<10x?xi32>>, !fir.heap<!fir.array<10x?xi32>>)
+// CHECK: hlfir.assign %[[VAL_0]] to %[[VAL_7]]#0 : !fir.class<!fir.array<10x?xi32>>, !fir.box<!fir.array<10x?xi32>>
+// CHECK: %[[VAL_8:.*]] = fir.undefined tuple<!fir.box<!fir.array<10x?xi32>>, i1>
+// CHECK: %[[VAL_9:.*]] = fir.insert_value %[[VAL_8]], %[[VAL_6]], [1 : index] : (tuple<!fir.box<!fir.array<10x?xi32>>, i1>, i1) -> tuple<!fir.box<!fir.array<10x?xi32>>, i1>
+// CHECK: %[[VAL_10:.*]] = fir.insert_value %[[VAL_9]], %[[VAL_7]]#0, [0 : index] : (tuple<!fir.box<!fir.array<10x?xi32>>, i1>, !fir.box<!fir.array<10x?xi32>>) -> tuple<!fir.box<!fir.array<10x?xi32>>, i1>
More information about the flang-commits
mailing list