[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