diff --git a/flang/include/flang/Optimizer/Transforms/Passes.h b/flang/include/flang/Optimizer/Transforms/Passes.h --- a/flang/include/flang/Optimizer/Transforms/Passes.h +++ b/flang/include/flang/Optimizer/Transforms/Passes.h @@ -9,6 +9,7 @@ #ifndef FORTRAN_OPTIMIZER_TRANSFORMS_PASSES_H #define FORTRAN_OPTIMIZER_TRANSFORMS_PASSES_H +#include "flang/Optimizer/Dialect/FIROps.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassRegistry.h" #include @@ -28,6 +29,7 @@ //===----------------------------------------------------------------------===// std::unique_ptr createAbstractResultOnFuncOptPass(); +std::unique_ptr createAbstractResultOnGlobalOptPass(); std::unique_ptr createAffineDemotionPass(); std::unique_ptr createArrayValueCopyPass(); std::unique_ptr createFirToCfgPass(); diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td b/flang/include/flang/Optimizer/Transforms/Passes.td --- a/flang/include/flang/Optimizer/Transforms/Passes.td +++ b/flang/include/flang/Optimizer/Transforms/Passes.td @@ -39,6 +39,10 @@ let constructor = "::fir::createAbstractResultOnFuncOptPass()"; } +def AbstractResultOnGlobalOpt : AbstractResultOptBase<"global", "fir::GlobalOp"> { + let constructor = "::fir::createAbstractResultOnGlobalOptPass()"; +} + def AffineDialectPromotion : Pass<"promote-to-affine", "::mlir::func::FuncOp"> { let summary = "Promotes `fir.{do_loop,if}` to `affine.{for,if}`."; let description = [{ diff --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc --- a/flang/include/flang/Tools/CLOptions.inc +++ b/flang/include/flang/Tools/CLOptions.inc @@ -195,6 +195,8 @@ fir::addBoxedProcedurePass(pm); pm.addNestedPass( fir::createAbstractResultOnFuncOptPass()); + pm.addNestedPass( + fir::createAbstractResultOnGlobalOptPass()); fir::addCodeGenRewritePass(pm); fir::addTargetRewritePass(pm); fir::addExternalNameConversionPass(pm); diff --git a/flang/lib/Optimizer/Transforms/AbstractResult.cpp b/flang/lib/Optimizer/Transforms/AbstractResult.cpp --- a/flang/lib/Optimizer/Transforms/AbstractResult.cpp +++ b/flang/lib/Optimizer/Transforms/AbstractResult.cpp @@ -277,9 +277,39 @@ } } }; + +inline static bool containsFunctionTypeWithAbstractResult(mlir::Type type) { + return mlir::TypeSwitch(type) + .Case([](fir::BoxProcType boxProc) { + return fir::hasAbstractResult( + boxProc.getEleTy().cast()); + }) + .Case([](fir::PointerType pointer) { + return fir::hasAbstractResult( + pointer.getEleTy().cast()); + }) + .Default([](auto &&) { return false; }); +} + +class AbstractResultOnGlobalOpt + : public AbstractResultOptTemplate { +public: + void runOnSpecificOperation(fir::GlobalOp global, bool, + mlir::RewritePatternSet &, + mlir::ConversionTarget &) { + if (containsFunctionTypeWithAbstractResult(global.getType())) { + TODO(global->getLoc(), "support for procedure pointers"); + } + } +}; } // end anonymous namespace } // namespace fir std::unique_ptr fir::createAbstractResultOnFuncOptPass() { return std::make_unique(); } + +std::unique_ptr fir::createAbstractResultOnGlobalOptPass() { + return std::make_unique(); +} diff --git a/flang/lib/Optimizer/Transforms/PassDetail.h b/flang/lib/Optimizer/Transforms/PassDetail.h --- a/flang/lib/Optimizer/Transforms/PassDetail.h +++ b/flang/lib/Optimizer/Transforms/PassDetail.h @@ -9,6 +9,7 @@ #define FORTRAN_OPTMIZER_TRANSFORMS_PASSDETAIL_H #include "flang/Optimizer/Dialect/FIRDialect.h" +#include "flang/Optimizer/Dialect/FIROps.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -52,8 +52,11 @@ ! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: BoxedProcedurePass -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOnFuncOpt +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +! ALL-NEXT: 'fir.global' Pipeline +! ALL-NEXT: AbstractResultOnGlobalOpt +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: AbstractResultOnFuncOpt ! ALL-NEXT: CodeGenRewrite ! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated diff --git a/flang/test/Fir/abstract-results.fir b/flang/test/Fir/abstract-results.fir --- a/flang/test/Fir/abstract-results.fir +++ b/flang/test/Fir/abstract-results.fir @@ -3,6 +3,8 @@ // RUN: fir-opt %s --abstract-result-on-func-opt | FileCheck %s --check-prefix=FUNC-REF // RUN: fir-opt %s --abstract-result-on-func-opt=abstract-result-as-box | FileCheck %s --check-prefix=FUNC-BOX +// RUN: fir-opt %s --abstract-result-on-global-opt | FileCheck %s --check-prefix=GLOBAL-REF +// RUN: fir-opt %s --abstract-result-on-global-opt=abstract-result-as-box | FileCheck %s --check-prefix=GLOBAL-BOX // ----------------------- Test declaration rewrite ---------------------------- @@ -253,3 +255,24 @@ // FUNC-BOX: fir.call %[[conv]](%[[box]], %c100) : (!fir.box>, index) -> () // FUNC-BOX-NOT: fir.save_result } + +// ----------------------- Test GlobalOp rewrite ------------------------ + +// This is needed to separate GlobalOp tests from FuncOp tests for FileCheck +// FUNC-REF-LABEL: fir.global {{.*}} : {{.*}} { +// FUNC-BOX-LABEL: fir.global {{.*}} : {{.*}} { + +// GLOBAL-REF-LABEL: fir.global @global_test_address_of : i32 { +// GLOBAL-BOX-LABEL: fir.global @global_test_address_of : i32 { +fir.global @global_test_address_of : i32 { + %0 = fir.address_of(@arrayfunc) : (i32) -> !fir.array + + // GLOBAL-REF: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.ref>, i32) -> () + // GLOBAL-REF: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.ref>, i32) -> ()) -> ((i32) -> !fir.array) + + // GLOBAL-BOX: %[[addrOf:.*]] = fir.address_of(@arrayfunc) : (!fir.box>, i32) -> () + // GLOBAL-BOX: %[[conv:.*]] = fir.convert %[[addrOf]] : ((!fir.box>, i32) -> ()) -> ((i32) -> !fir.array) + + %c42 = arith.constant 42 : i32 + fir.has_value %c42 : i32 +} diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -52,8 +52,11 @@ // PASSES-NEXT: (S) 0 num-dce'd - Number of operations DCE'd // PASSES-NEXT: BoxedProcedurePass -// PASSES-NEXT: 'func.func' Pipeline -// PASSES-NEXT: AbstractResultOnFuncOpt +// PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func'] +// PASSES-NEXT: 'fir.global' Pipeline +// PASSES-NEXT: AbstractResultOnGlobalOpt +// PASSES-NEXT: 'func.func' Pipeline +// PASSES-NEXT: AbstractResultOnFuncOpt // PASSES-NEXT: CodeGenRewrite // PASSES-NEXT: (S) 0 num-dce'd - Number of operations eliminated