[flang-commits] [flang] 3b29159 - [flang] Add hlfir.declare codegen

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Nov 14 02:20:25 PST 2022


Author: Jean Perier
Date: 2022-11-14T11:19:35+01:00
New Revision: 3b29159da0945cd657aa4ef4ca52c7a386dd72b3

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

LOG: [flang] Add hlfir.declare codegen

hlfir.declare codegen generates a fir.declare, and may generate a
fir.embox/fir.rebox/fir.emboxchar if the base value does not convey
all the variable bounds and length parameter information.

Leave OPTIONAL as a TODO to keep this patch simple. It will require
making the embox/rebox optional to preserve the optionality aspects.

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

Added: 
    flang/include/flang/Optimizer/HLFIR/Passes.h
    flang/include/flang/Optimizer/HLFIR/Passes.td
    flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
    flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
    flang/test/HLFIR/declare-codegen.fir

Modified: 
    flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td
    flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
    flang/lib/Frontend/CMakeLists.txt
    flang/lib/Optimizer/HLFIR/CMakeLists.txt
    flang/tools/bbc/CMakeLists.txt
    flang/tools/fir-opt/CMakeLists.txt
    flang/tools/fir-opt/fir-opt.cpp
    flang/tools/tco/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td b/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td
index 1cd1abb1bf59f..ed6b3bb2c7c99 100644
--- a/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td
+++ b/flang/include/flang/Optimizer/Dialect/FortranVariableInterface.td
@@ -85,7 +85,7 @@ def fir_FortranVariableOpInterface : OpInterface<"FortranVariableOpInterface"> {
       return fir::unwrapSequenceType(getElementOrSequenceType());
     }
 
-    /// Is the variable an array ?
+    /// Is the variable an array?
     bool isArray() {
       return getElementOrSequenceType().isa<fir::SequenceType>();
     }
@@ -101,26 +101,33 @@ def fir_FortranVariableOpInterface : OpInterface<"FortranVariableOpInterface"> {
       return 0;
     }
 
-    /// Is this variable a Fortran pointer ?
+    /// Is this variable a Fortran pointer?
     bool isPointer() {
       auto attrs = getFortranAttrs();
       return attrs && bitEnumContainsAny(*attrs,
                         fir::FortranVariableFlagsEnum::pointer);
     }
 
-    /// Is this variable a Fortran allocatable ?
+    /// Is this variable a Fortran allocatable?
     bool isAllocatable() {
       auto attrs = getFortranAttrs();
       return attrs && bitEnumContainsAny(*attrs,
                         fir::FortranVariableFlagsEnum::allocatable);
     }
 
-    /// Is this a Fortran character variable ?
+    /// Is this variable a Fortran optional?
+    bool isOptional() {
+      auto attrs = getFortranAttrs();
+      return attrs && bitEnumContainsAny(*attrs,
+                        fir::FortranVariableFlagsEnum::optional);
+    }
+
+    /// Is this a Fortran character variable?
     bool isCharacter() {
       return getElementType().isa<fir::CharacterType>();
     }
 
-    /// Is this a Fortran character variable with an explicit length ?
+    /// Is this a Fortran character variable with an explicit length?
     bool hasExplicitCharLen() {
       return isCharacter() && !getExplicitTypeParams().empty();
     }
@@ -131,23 +138,23 @@ def fir_FortranVariableOpInterface : OpInterface<"FortranVariableOpInterface"> {
       return getExplicitTypeParams()[0];
     }
 
-    /// Is this variable represented as a fir.box or fir.class value ?
+    /// Is this variable represented as a fir.box or fir.class value?
     bool isBoxValue() {
       return getBase().getType().isa<fir::BaseBoxType>();
     }
 
-    /// Is this variable represented as a fir.box or fir.class address ?
+    /// Is this variable represented as a fir.box or fir.class address?
     bool isBoxAddress() {
       return fir::isBoxAddress(getBase().getType());
     }
 
     /// Is this variable represented as the value or address of a fir.box or
-    /// fir.class ?
+    /// fir.class?
     bool isBox() {
       return fir::isBoxAddressOrValue(getBase().getType());
     }
 
-    /// Interface verifier imlementation for declare operations
+    /// Interface verifier imlementation for declare operations.
     mlir::LogicalResult verifyDeclareLikeOpImpl(mlir::Value memRef);
 
   }];

diff  --git a/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt b/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
index 31ce88e84cb5b..18f2cef35509c 100644
--- a/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
+++ b/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
@@ -10,4 +10,7 @@ set(LLVM_TARGET_DEFINITIONS HLFIROps.td)
 mlir_tablegen(HLFIROps.h.inc -gen-op-decls)
 mlir_tablegen(HLFIROps.cpp.inc -gen-op-defs)
 
+set(LLVM_TARGET_DEFINITIONS Passes.td)
+mlir_tablegen(Passes.h.inc -gen-pass-decls -name HLFIR)
+
 add_public_tablegen_target(HLFIROpsIncGen)

diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h
new file mode 100644
index 0000000000000..3e3637a782a89
--- /dev/null
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.h
@@ -0,0 +1,30 @@
+//===- Passes.h - HLFIR pass entry points ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header declares HLFIR pass entry points.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_HLFIR_PASSES_H
+#define FORTRAN_OPTIMIZER_HLFIR_PASSES_H
+
+#include "mlir/Pass/Pass.h"
+#include "mlir/Pass/PassRegistry.h"
+#include <memory>
+
+namespace hlfir {
+#define GEN_PASS_DECL
+#include "flang/Optimizer/HLFIR/Passes.h.inc"
+
+std::unique_ptr<mlir::Pass> createConvertHLFIRtoFIRPass();
+
+#define GEN_PASS_REGISTRATION
+#include "flang/Optimizer/HLFIR/Passes.h.inc"
+} // namespace hlfir
+
+#endif // FORTRAN_OPTIMIZER_HLFIR_PASSES_H

diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td
new file mode 100644
index 0000000000000..bdb4dc447083a
--- /dev/null
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.td
@@ -0,0 +1,18 @@
+//===-- Passes.td - HLFIR pass definition file -------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_DIALECT_HLFIR_PASSES
+#define FORTRAN_DIALECT_HLFIR_PASSES
+
+include "mlir/Pass/PassBase.td"
+def ConvertHLFIRtoFIR : Pass<"convert-hlfir-to-fir", "::mlir::func::FuncOp"> {
+  let summary = "Lower High-Level FIR to FIR";
+  let constructor = "hlfir::createConvertHLFIRtoFIRPass()";
+}
+
+#endif //FORTRAN_DIALECT_HLFIR_PASSES

diff  --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index d3947f64d0295..3fa7960781184 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -33,6 +33,7 @@ add_flang_library(flangFrontend
   FIRCodeGen
   FIRTransforms
   HLFIRDialect
+  HLFIRTransforms
   MLIRTransforms
   MLIRLLVMToLLVMIRTranslation
   MLIRSCFToControlFlow

diff  --git a/flang/lib/Optimizer/HLFIR/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/CMakeLists.txt
index f33061b2d87cf..9f57627c321fb 100644
--- a/flang/lib/Optimizer/HLFIR/CMakeLists.txt
+++ b/flang/lib/Optimizer/HLFIR/CMakeLists.txt
@@ -1 +1,2 @@
 add_subdirectory(IR)
+add_subdirectory(Transforms)

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..587f00f3c471e
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
@@ -0,0 +1,23 @@
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_flang_library(HLFIRTransforms
+  ConvertToFIR.cpp
+
+  DEPENDS
+  FIRDialect
+  HLFIROpsIncGen
+  ${dialect_libs}
+
+  LINK_LIBS
+  FIRDialect
+  FIRBuilder
+  FIRSupport
+  HLFIRDialect
+  MLIRIR
+  ${dialect_libs}
+
+  LINK_COMPONENTS
+  AsmParser
+  AsmPrinter
+  Remarks
+)

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
new file mode 100644
index 0000000000000..0b87ab0d0a54a
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
@@ -0,0 +1,119 @@
+//===- ConvertToFIR.cpp - Convert HLFIR to FIR ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This file defines a pass to lower HLFIR to FIR
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/HLFIRTools.h"
+#include "flang/Optimizer/Builder/MutableBox.h"
+#include "flang/Optimizer/Builder/Runtime/Assign.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
+#include "flang/Optimizer/Dialect/FIRType.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
+#include "flang/Optimizer/Support/FIRContext.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace hlfir {
+#define GEN_PASS_DEF_CONVERTHLFIRTOFIR
+#include "flang/Optimizer/HLFIR/Passes.h.inc"
+} // namespace hlfir
+
+using namespace mlir;
+
+namespace {
+class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
+public:
+  explicit DeclareOpConversion(mlir::MLIRContext *ctx)
+      : OpRewritePattern{ctx} {}
+
+  mlir::LogicalResult
+  matchAndRewrite(hlfir::DeclareOp declareOp,
+                  mlir::PatternRewriter &rewriter) const override {
+    mlir::Location loc = declareOp->getLoc();
+    mlir::Value memref = declareOp.getMemref();
+    fir::FortranVariableFlagsAttr fortranAttrs;
+    if (auto attrs = declareOp.getFortranAttrs())
+      fortranAttrs =
+          fir::FortranVariableFlagsAttr::get(rewriter.getContext(), *attrs);
+    auto firBase = rewriter
+                       .create<fir::DeclareOp>(
+                           loc, memref.getType(), memref, declareOp.getShape(),
+                           declareOp.getTypeparams(), declareOp.getUniqName(),
+                           fortranAttrs)
+                       .getResult();
+    mlir::Value hlfirBase;
+    mlir::Type hlfirBaseType = declareOp.getBase().getType();
+    if (hlfirBaseType.isa<fir::BaseBoxType>()) {
+      // Need to conditionally rebox/embox for optional.
+      if (mlir::cast<fir::FortranVariableOpInterface>(declareOp.getOperation())
+              .isOptional())
+        TODO(loc, "converting hlfir declare of optional box to fir");
+      if (!firBase.getType().isa<fir::BaseBoxType>()) {
+        llvm::SmallVector<mlir::Value> typeParams;
+        auto maybeCharType =
+            fir::unwrapSequenceType(fir::unwrapPassByRefType(hlfirBaseType))
+                .dyn_cast<fir::CharacterType>();
+        if (!maybeCharType || maybeCharType.hasDynamicLen())
+          typeParams.append(declareOp.getTypeparams().begin(),
+                            declareOp.getTypeparams().end());
+        hlfirBase = rewriter.create<fir::EmboxOp>(
+            loc, hlfirBaseType, firBase, declareOp.getShape(),
+            /*slice=*/mlir::Value{}, typeParams);
+      } else {
+        // Rebox so that lower bounds are correct.
+        hlfirBase = rewriter.create<fir::ReboxOp>(loc, hlfirBaseType, firBase,
+                                                  declareOp.getShape(),
+                                                  /*slice=*/mlir::Value{});
+      }
+    } else if (hlfirBaseType.isa<fir::BoxCharType>()) {
+      assert(declareOp.getTypeparams().size() == 1 &&
+             "must contain character length");
+      hlfirBase = rewriter.create<fir::EmboxCharOp>(
+          loc, hlfirBaseType, firBase, declareOp.getTypeparams()[0]);
+    } else {
+      if (hlfirBaseType != firBase.getType()) {
+        declareOp.emitOpError()
+            << "unhandled HLFIR variable type '" << hlfirBaseType << "'\n";
+        return mlir::failure();
+      }
+      hlfirBase = firBase;
+    }
+    rewriter.replaceOp(declareOp, {hlfirBase, firBase});
+    return mlir::success();
+  }
+};
+
+class ConvertHLFIRtoFIR
+    : public hlfir::impl::ConvertHLFIRtoFIRBase<ConvertHLFIRtoFIR> {
+public:
+  void runOnOperation() override {
+    auto func = this->getOperation();
+    auto *context = &getContext();
+    mlir::RewritePatternSet patterns(context);
+    patterns.insert<DeclareOpConversion>(context);
+    mlir::ConversionTarget target(*context);
+    target.addIllegalDialect<hlfir::hlfirDialect>();
+    target.markUnknownOpDynamicallyLegal(
+        [](mlir::Operation *) { return true; });
+    if (mlir::failed(
+            mlir::applyPartialConversion(func, target, std::move(patterns)))) {
+      mlir::emitError(mlir::UnknownLoc::get(context),
+                      "failure in HLFIR to FIR conversion pass");
+      signalPassFailure();
+    }
+  }
+};
+
+} // namespace
+
+std::unique_ptr<mlir::Pass> hlfir::createConvertHLFIRtoFIRPass() {
+  return std::make_unique<ConvertHLFIRtoFIR>();
+}

diff  --git a/flang/test/HLFIR/declare-codegen.fir b/flang/test/HLFIR/declare-codegen.fir
new file mode 100644
index 0000000000000..601ad4cdc2da1
--- /dev/null
+++ b/flang/test/HLFIR/declare-codegen.fir
@@ -0,0 +1,180 @@
+// Test hlfir.declare operation code generation to FIR
+
+// RUN: fir-opt %s -convert-hlfir-to-fir | FileCheck %s
+
+func.func @numeric_declare(%arg0: !fir.ref<f32>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+  return
+}
+// CHECK-LABEL:   func.func @numeric_declare(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<f32>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.ref<f32>) -> !fir.ref<f32>
+
+
+func.func @char_declare(%arg0: !fir.boxchar<1> ) {
+  %0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+  %1:2 = hlfir.declare %0#0 typeparams %0#1 {uniq_name = "c"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+  return
+}
+// CHECK-LABEL:   func.func @char_declare(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.boxchar<1>) {
+// CHECK:  %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+// CHECK:         %[[VAL_2:.*]] = fir.declare %[[VAL_1]]#0 typeparams %[[VAL_1]]#1 {uniq_name = "c"} : (!fir.ref<!fir.char<1,?>>, index) -> !fir.ref<!fir.char<1,?>>
+// CHECK:         %[[VAL_3:.*]] = fir.emboxchar %[[VAL_2]], %[[VAL_1]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+
+
+func.func @derived_declare(%arg0: !fir.ref<!fir.type<t{field:i32}>>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.ref<!fir.type<t{field:i32}>>) -> (!fir.ref<!fir.type<t{field:i32}>>, !fir.ref<!fir.type<t{field:i32}>>)
+  return
+}
+// CHECK-LABEL:   func.func @derived_declare(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.type<t{field:i32}>>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.ref<!fir.type<t{field:i32}>>) -> !fir.ref<!fir.type<t{field:i32}>>
+
+
+func.func @pdt_declare(%arg0: !fir.ref<!fir.type<pdt(param:i32){field:i32}>>) {
+  %c1 = arith.constant 1 : index
+  %0:2 = hlfir.declare %arg0 typeparams %c1 {uniq_name = "x"} : (!fir.ref<!fir.type<pdt(param:i32){field:i32}>>, index) -> (!fir.box<!fir.type<pdt(param:i32){field:i32}>>, !fir.ref<!fir.type<pdt(param:i32){field:i32}>>)
+  return
+}
+// CHECK-LABEL:   func.func @pdt_declare(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.type<pdt(param:i32){field:i32}>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:         %[[VAL_2:.*]] = fir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "x"} : (!fir.ref<!fir.type<pdt(param:i32){field:i32}>>, index) -> !fir.ref<!fir.type<pdt(param:i32){field:i32}>>
+// CHECK:         %[[VAL_3:.*]] = fir.embox %[[VAL_2]] typeparams %[[VAL_1]] : (!fir.ref<!fir.type<pdt(param:i32){field:i32}>>, index) -> !fir.box<!fir.type<pdt(param:i32){field:i32}>>
+
+
+func.func @array_declare(%arg0: !fir.ref<!fir.array<?x?xf32>>) {
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %shape = fir.shape %c1, %c2 : (index, index) -> !fir.shape<2>
+  %0:2 = hlfir.declare %arg0(%shape) {uniq_name = "x"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<?x?xf32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 2 : index
+// CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
+// CHECK:         %[[VAL_4:.*]] = fir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "x"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK:         %[[VAL_5:.*]] = fir.embox %[[VAL_4]](%[[VAL_3]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.array<?x?xf32>>
+
+
+func.func @array_declare_2(%arg0: !fir.ref<!fir.array<?x?xf32>>) {
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %c3 = arith.constant 3 : index
+  %c4 = arith.constant 4 : index
+  %shape = fir.shape_shift %c1, %c2, %c3, %c4 : (index, index, index, index) -> !fir.shapeshift<2>
+  %0:2 = hlfir.declare %arg0(%shape) {uniq_name = "x"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.ref<!fir.array<?x?xf32>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_2(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<?x?xf32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 2 : index
+// CHECK:  %[[VAL_3:.*]] = arith.constant 3 : index
+// CHECK:  %[[VAL_4:.*]] = arith.constant 4 : index
+// CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shapeshift<2>
+// CHECK:         %[[VAL_6:.*]] = fir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "x"} : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<?x?xf32>>
+// CHECK:         %[[VAL_7:.*]] = fir.embox %[[VAL_6]](%[[VAL_5]]) : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>) -> !fir.box<!fir.array<?x?xf32>>
+
+func.func @array_declare_constant_extents_with_lower_bounds(%arg0: !fir.ref<!fir.array<2x4xf32>>) {
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %c3 = arith.constant 3 : index
+  %c4 = arith.constant 4 : index
+  %shape = fir.shape_shift %c1, %c2, %c3, %c4 : (index, index, index, index) -> !fir.shapeshift<2>
+  %0:2 = hlfir.declare %arg0(%shape) {uniq_name = "x"} : (!fir.ref<!fir.array<2x4xf32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<2x4xf32>>, !fir.ref<!fir.array<2x4xf32>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_constant_extents_with_lower_bounds(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.array<2x4xf32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 2 : index
+// CHECK:  %[[VAL_3:.*]] = arith.constant 3 : index
+// CHECK:  %[[VAL_4:.*]] = arith.constant 4 : index
+// CHECK:  %[[VAL_5:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shapeshift<2>
+// CHECK:         %[[VAL_6:.*]] = fir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "x"} : (!fir.ref<!fir.array<2x4xf32>>, !fir.shapeshift<2>) -> !fir.ref<!fir.array<2x4xf32>>
+// CHECK:         %[[VAL_7:.*]] = fir.embox %[[VAL_6]](%[[VAL_5]]) : (!fir.ref<!fir.array<2x4xf32>>, !fir.shapeshift<2>) -> !fir.box<!fir.array<2x4xf32>>
+
+
+func.func @array_declare_box(%arg0: !fir.box<!fir.array<?x?xf32>>) {
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %shape = fir.shift %c1, %c2 : (index, index) -> !fir.shift<2>
+  %0:2 = hlfir.declare %arg0(%shape) {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_box(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 2 : index
+// CHECK:  %[[VAL_3:.*]] = fir.shift %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shift<2>
+// CHECK:         %[[VAL_4:.*]] = fir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK:         %[[VAL_5:.*]] = fir.rebox %[[VAL_4]](%[[VAL_3]]) : (!fir.box<!fir.array<?x?xf32>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?xf32>>
+
+
+func.func @array_declare_box_2(%arg0: !fir.box<!fir.array<?x?xf32>>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_box_2(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+// CHECK:         %[[VAL_2:.*]] = fir.rebox %[[VAL_1]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
+
+func.func @array_declare_char_box(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_char_box(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+// CHECK:         %[[VAL_2:.*]] = fir.rebox %[[VAL_1]] : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+
+
+func.func @array_declare_char_box_2(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
+  %c1 = arith.constant 1 : index
+  %c2 = arith.constant 2 : index
+  %c3 = arith.constant 3 : index
+  %shape = fir.shift %c1, %c2 : (index, index) -> !fir.shift<2>
+  %0:2 = hlfir.declare %arg0(%shape) typeparams %c3 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.shift<2>, index) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>)
+  return
+}
+// CHECK-LABEL:   func.func @array_declare_char_box_2(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 1 : index
+// CHECK:  %[[VAL_2:.*]] = arith.constant 2 : index
+// CHECK:  %[[VAL_3:.*]] = arith.constant 3 : index
+// CHECK:  %[[VAL_4:.*]] = fir.shift %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shift<2>
+// CHECK:         %[[VAL_5:.*]] = fir.declare %[[VAL_0]](%[[VAL_4]]) typeparams %[[VAL_3]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.shift<2>, index) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+// CHECK:         %[[VAL_6:.*]] = fir.rebox %[[VAL_5]](%[[VAL_4]]) : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.shift<2>) -> !fir.box<!fir.array<?x?x!fir.char<1,?>>>
+
+
+func.func @array_declare_char_boxaddr(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>)
+  return
+}
+// CHECK-LABEL: func.func @array_declare_char_boxaddr(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>
+
+
+func.func @array_declare_char_boxaddr_2(%arg0: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) {
+  %c3 = arith.constant 3 : index
+  %0:2 = hlfir.declare %arg0 typeparams %c3 {uniq_name = "x"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>, index) -> (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>, !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>)
+  return
+}
+// CHECK-LABEL: func.func @array_declare_char_boxaddr_2(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 3 : index
+// CHECK:         %[[VAL_2:.*]] = fir.declare %[[VAL_0]] typeparams %[[VAL_1]] {uniq_name = "x"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>, index) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.char<1,?>>>>>
+
+func.func @array_declare_unlimited_polymorphic_boxaddr(%arg0: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) {
+  %0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) -> (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>, !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>)
+  return
+}
+// CHECK-LABEL: func.func @array_declare_unlimited_polymorphic_boxaddr(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) {
+// CHECK:         %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>) -> !fir.ref<!fir.class<!fir.ptr<!fir.array<?x?xnone>>>>

diff  --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt
index c8b1616b3b8f3..d42842e23e408 100644
--- a/flang/tools/bbc/CMakeLists.txt
+++ b/flang/tools/bbc/CMakeLists.txt
@@ -15,6 +15,7 @@ FIRSupport
 FIRTransforms
 FIRBuilder
 HLFIRDialect
+HLFIRTransforms
 ${dialect_libs}
 MLIRAffineToStandard
 MLIRSCFToControlFlow

diff  --git a/flang/tools/fir-opt/CMakeLists.txt b/flang/tools/fir-opt/CMakeLists.txt
index 1914c370a407e..ecfb295ace0e1 100644
--- a/flang/tools/fir-opt/CMakeLists.txt
+++ b/flang/tools/fir-opt/CMakeLists.txt
@@ -14,6 +14,7 @@ target_link_libraries(fir-opt PRIVATE
   FIRTransforms
   FIRCodeGen
   HLFIRDialect
+  HLFIRTransforms
   FIRAnalysis
   ${test_libs}
   ${dialect_libs}

diff  --git a/flang/tools/fir-opt/fir-opt.cpp b/flang/tools/fir-opt/fir-opt.cpp
index a35960be75e6b..b605c9dc52af4 100644
--- a/flang/tools/fir-opt/fir-opt.cpp
+++ b/flang/tools/fir-opt/fir-opt.cpp
@@ -13,6 +13,7 @@
 
 #include "mlir/Tools/mlir-opt/MlirOptMain.h"
 #include "flang/Optimizer/CodeGen/CodeGen.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
 #include "flang/Optimizer/Support/InitFIR.h"
 #include "flang/Optimizer/Transforms/Passes.h"
 
@@ -27,6 +28,7 @@ int main(int argc, char **argv) {
   fir::support::registerMLIRPassesForFortranTools();
   fir::registerOptCodeGenPasses();
   fir::registerOptTransformPasses();
+  hlfir::registerHLFIRPasses();
 #ifdef FLANG_INCLUDE_TESTS
   fir::test::registerTestFIRAliasAnalysisPass();
 #endif

diff  --git a/flang/tools/tco/CMakeLists.txt b/flang/tools/tco/CMakeLists.txt
index 4a3e2a8359ba7..28cbbb5154ccf 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries(tco PRIVATE
   FIRTransforms
   FIRBuilder
   HLFIRDialect
+  HLFIRTransforms
   ${dialect_libs}
   MLIRIR
   MLIRLLVMDialect


        


More information about the flang-commits mailing list