[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