forked from OSchip/llvm-project
[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:
parent
7e4cfcdb6f
commit
3b29159da0
|
@ -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);
|
||||
|
||||
}];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -33,6 +33,7 @@ add_flang_library(flangFrontend
|
|||
FIRCodeGen
|
||||
FIRTransforms
|
||||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
MLIRTransforms
|
||||
MLIRLLVMToLLVMIRTranslation
|
||||
MLIRSCFToControlFlow
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
add_subdirectory(IR)
|
||||
add_subdirectory(Transforms)
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -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>();
|
||||
}
|
|
@ -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>>>>
|
|
@ -15,6 +15,7 @@ FIRSupport
|
|||
FIRTransforms
|
||||
FIRBuilder
|
||||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
${dialect_libs}
|
||||
MLIRAffineToStandard
|
||||
MLIRSCFToControlFlow
|
||||
|
|
|
@ -14,6 +14,7 @@ target_link_libraries(fir-opt PRIVATE
|
|||
FIRTransforms
|
||||
FIRCodeGen
|
||||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
FIRAnalysis
|
||||
${test_libs}
|
||||
${dialect_libs}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,7 @@ target_link_libraries(tco PRIVATE
|
|||
FIRTransforms
|
||||
FIRBuilder
|
||||
HLFIRDialect
|
||||
HLFIRTransforms
|
||||
${dialect_libs}
|
||||
MLIRIR
|
||||
MLIRLLVMDialect
|
||||
|
|
Loading…
Reference in New Issue