[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
This commit is contained in:
Jean Perier 2022-11-14 11:19:21 +01:00
parent 7e4cfcdb6f
commit 3b29159da0
13 changed files with 396 additions and 9 deletions

View File

@ -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);
}];

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -33,6 +33,7 @@ add_flang_library(flangFrontend
FIRCodeGen
FIRTransforms
HLFIRDialect
HLFIRTransforms
MLIRTransforms
MLIRLLVMToLLVMIRTranslation
MLIRSCFToControlFlow

View File

@ -1 +1,2 @@
add_subdirectory(IR)
add_subdirectory(Transforms)

View File

@ -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
)

View File

@ -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>();
}

View File

@ -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>>>>

View File

@ -15,6 +15,7 @@ FIRSupport
FIRTransforms
FIRBuilder
HLFIRDialect
HLFIRTransforms
${dialect_libs}
MLIRAffineToStandard
MLIRSCFToControlFlow

View File

@ -14,6 +14,7 @@ target_link_libraries(fir-opt PRIVATE
FIRTransforms
FIRCodeGen
HLFIRDialect
HLFIRTransforms
FIRAnalysis
${test_libs}
${dialect_libs}

View File

@ -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

View File

@ -12,6 +12,7 @@ target_link_libraries(tco PRIVATE
FIRTransforms
FIRBuilder
HLFIRDialect
HLFIRTransforms
${dialect_libs}
MLIRIR
MLIRLLVMDialect