llvm-project/flang/lib/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.cpp
Razvan Lupusoru e63e55cae8
[mlir][acc] Add ACCRecipeMaterialization pass and reduction ops (#184252)
Pass
----
Add the `acc-recipe-materialization` pass, which materializes OpenACC
privatization, firstprivate and reduction recipes by inlining their
init, copy, combiner, and destroy regions into the operation for the
construct. The pass runs on acc.parallel, acc.serial, acc.kernels, and
acc.loop.

- Firstprivate: Inserts acc.firstprivate_map so the initial value is
available on the device, then clones the recipe init and copy regions
into the construct and replaces uses with the materialized alloca.
Optional destroy region is cloned before the region terminator.

- Private: Clones the recipe init region into the construct (at region
entry or at the loop op for acc.loop private). Replaces uses of the
recipe result with the materialized alloca. Optional destroy region is
cloned before the region terminator.

- Reduction: Creates acc.reduction_init (init region inlined) and
acc.reduction_combine_region (combiner region inlined). All uses of the
reduction in the region are updated to the reduction init result.

New operations
--------------
- acc.reduction_init: Allocates and initializes a private reduction
variable from a recipe. Takes the original reduction variable and
reduction_operator; has a single region that must yield one value (the
private storage) via acc.yield. Used by the pass to materialize
acc.reduction_recipe init regions inside the compute construct.

- acc.reduction_combine_region: Combines the private reduction value
with the shared reduction variable. Takes the shared and private
memrefs; has a single region (the recipe combiner) terminated by
acc.yield with no operands. Used by the pass to materialize the
reduction recipe combiner.

Both ops implement RegionBranchOpInterface. acc.yield is updated to
allow terminating ReductionInitOp and ReductionCombineRegionOp regions.

Supporting changes
------------------
- OpenACCUtilsLoop: Factor cloneACCRegionInto out of the existing
loop-conversion helper so the pass can clone recipe regions with
optional result replacement; loop conversion now calls the shared
helper.
- Flang: Add ReductionInitOpFortranObjectViewModel
(FortranObjectViewOpInterface) for acc.reduction_init and register it in
OpenACC extensions.

Tests
-----
- MLIR: acc-recipe-materialization-{firstprivate,private,reduction,
kernel-private,parallel}.mlir (memref dialect).
- Flang: acc-recipe-materialization-{firstprivate,firstprivate-derived,
private,reduction,kernel-private,parallel}.fir; firstprivate test has a
second RUN with -acc-optimize-firstprivate-map.

---------

Co-authored-by: Scott Manley <rscottmanley@gmail.com>
2026-03-02 17:35:22 -08:00

109 lines
4.5 KiB
C++

//===-- RegisterOpenACCExtensions.cpp -------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Registration for OpenACC extensions as applied to FIR dialect.
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/OpenACC/Support/RegisterOpenACCExtensions.h"
#include "flang/Optimizer/Dialect/CUF/CUFDialect.h"
#include "flang/Optimizer/Dialect/CUF/CUFOps.h"
#include "flang/Optimizer/Dialect/FIRDialect.h"
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Optimizer/OpenACC/Support/FIROpenACCOpsInterfaces.h"
#include "flang/Optimizer/OpenACC/Support/FIROpenACCTypeInterfaces.h"
namespace fir::acc {
void registerOpenACCExtensions(mlir::DialectRegistry &registry) {
registry.addExtension(+[](mlir::MLIRContext *ctx,
fir::FIROpsDialect *dialect) {
fir::BoxType::attachInterface<OpenACCMappableModel<fir::BaseBoxType>>(*ctx);
fir::ClassType::attachInterface<OpenACCMappableModel<fir::BaseBoxType>>(
*ctx);
fir::ReferenceType::attachInterface<
OpenACCMappableModel<fir::ReferenceType>>(*ctx);
fir::PointerType::attachInterface<OpenACCMappableModel<fir::PointerType>>(
*ctx);
fir::HeapType::attachInterface<OpenACCMappableModel<fir::HeapType>>(*ctx);
fir::ReferenceType::attachInterface<
OpenACCPointerLikeModel<fir::ReferenceType>>(*ctx);
fir::PointerType::attachInterface<
OpenACCPointerLikeModel<fir::PointerType>>(*ctx);
fir::HeapType::attachInterface<OpenACCPointerLikeModel<fir::HeapType>>(
*ctx);
fir::LLVMPointerType::attachInterface<
OpenACCPointerLikeModel<fir::LLVMPointerType>>(*ctx);
fir::LogicalType::attachInterface<OpenACCReducibleLogicalModel>(*ctx);
fir::ArrayCoorOp::attachInterface<
PartialEntityAccessModel<fir::ArrayCoorOp>>(*ctx);
fir::CoordinateOp::attachInterface<
PartialEntityAccessModel<fir::CoordinateOp>>(*ctx);
fir::DeclareOp::attachInterface<PartialEntityAccessModel<fir::DeclareOp>>(
*ctx);
fir::AddrOfOp::attachInterface<AddressOfGlobalModel>(*ctx);
fir::GlobalOp::attachInterface<GlobalVariableModel>(*ctx);
fir::AllocaOp::attachInterface<IndirectGlobalAccessModel<fir::AllocaOp>>(
*ctx);
fir::EmboxOp::attachInterface<IndirectGlobalAccessModel<fir::EmboxOp>>(
*ctx);
fir::ReboxOp::attachInterface<IndirectGlobalAccessModel<fir::ReboxOp>>(
*ctx);
fir::TypeDescOp::attachInterface<
IndirectGlobalAccessModel<fir::TypeDescOp>>(*ctx);
// Attach OutlineRematerializationOpInterface to FIR operations that
// produce synthetic types (shapes, field indices) which cannot be passed
// as arguments to outlined regions and must be rematerialized inside.
fir::ShapeOp::attachInterface<OutlineRematerializationModel<fir::ShapeOp>>(
*ctx);
fir::ShapeShiftOp::attachInterface<
OutlineRematerializationModel<fir::ShapeShiftOp>>(*ctx);
fir::ShiftOp::attachInterface<OutlineRematerializationModel<fir::ShiftOp>>(
*ctx);
fir::FieldIndexOp::attachInterface<
OutlineRematerializationModel<fir::FieldIndexOp>>(*ctx);
});
// Register HLFIR operation interfaces
registry.addExtension(
+[](mlir::MLIRContext *ctx, hlfir::hlfirDialect *dialect) {
hlfir::DesignateOp::attachInterface<
PartialEntityAccessModel<hlfir::DesignateOp>>(*ctx);
hlfir::DeclareOp::attachInterface<
PartialEntityAccessModel<hlfir::DeclareOp>>(*ctx);
});
// Register CUF operation interfaces
registry.addExtension(+[](mlir::MLIRContext *ctx, cuf::CUFDialect *dialect) {
cuf::KernelOp::attachInterface<OffloadRegionModel<cuf::KernelOp>>(*ctx);
});
// Attach FIR dialect interfaces to OpenACC operations.
registry.addExtension(+[](mlir::MLIRContext *ctx,
mlir::acc::OpenACCDialect *dialect) {
mlir::acc::LoopOp::attachInterface<OperationMoveModel<mlir::acc::LoopOp>>(
*ctx);
mlir::acc::ReductionInitOp::attachInterface<
fir::acc::ReductionInitOpFortranObjectViewModel>(*ctx);
});
registerAttrsExtensions(registry);
}
} // namespace fir::acc