[flang-commits] [flang] [Flang] Legalize the hlfir.exactly_once operation (PR #152202)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 5 13:43:50 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Carlos Seo (ceseo)
<details>
<summary>Changes</summary>
When reshape is used with allocatable components in derived types within a where construct, a hlfir.exactly_once operation is generated. This commit implements the conversion pattern for it in the HLFIR bufferization pass.
Fixes #<!-- -->130532
---
Full diff: https://github.com/llvm/llvm-project/pull/152202.diff
2 Files Affected:
- (modified) flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp (+42-3)
- (added) flang/test/HLFIR/bufferize-exactly_once.f90 (+20)
``````````diff
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
index 9109f2b331567..327e385a11eec 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
@@ -29,6 +29,7 @@
#include "flang/Optimizer/OpenMP/Passes.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/IR/Dominance.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassManager.h"
@@ -880,6 +881,42 @@ struct EvaluateInMemoryOpConversion
}
};
+struct ExactlyOnceOpConversion
+ : public mlir::OpConversionPattern<hlfir::ExactlyOnceOp> {
+ using mlir::OpConversionPattern<hlfir::ExactlyOnceOp>::OpConversionPattern;
+ explicit ExactlyOnceOpConversion(mlir::MLIRContext *ctx)
+ : mlir::OpConversionPattern<hlfir::ExactlyOnceOp>{ctx} {}
+ llvm::LogicalResult
+ matchAndRewrite(hlfir::ExactlyOnceOp exactlyOnce, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const override {
+ fir::FirOpBuilder builder(rewriter, exactlyOnce.getOperation());
+
+ // The body of the exactly_once op may contain operations that will require
+ // to be translated
+ HLFIRListener listener{builder, rewriter};
+ builder.setListener(&listener);
+
+ // Clone the exactly_once region body and convert it inline
+ mlir::Region ®ion = exactlyOnce.getBody();
+ mlir::Block &block = region.front();
+ mlir::IRMapping mapper;
+
+ // Clone all operations except the terminator
+ for (auto &op : block.without_terminator()) {
+ rewriter.clone(op, mapper);
+ }
+
+ // Get the yielded value and replace the exactly_once operation with it.
+ // Later we will register the pattern and mark the ExactlyOnceOp as
+ // illegal (see below).
+ auto yield = mlir::cast<hlfir::YieldOp>(block.getTerminator());
+ mlir::Value yieldedValue = mapper.lookupOrDefault(yield.getEntity());
+
+ rewriter.replaceOp(exactlyOnce, yieldedValue);
+ return mlir::success();
+ }
+};
+
class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase<BufferizeHLFIR> {
public:
using BufferizeHLFIRBase<BufferizeHLFIR>::BufferizeHLFIRBase;
@@ -899,8 +936,9 @@ class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase<BufferizeHLFIR> {
AssociateOpConversion, CharExtremumOpConversion,
ConcatOpConversion, DestroyOpConversion,
EndAssociateOpConversion, EvaluateInMemoryOpConversion,
- NoReassocOpConversion, SetLengthOpConversion,
- ShapeOfOpConversion, GetLengthOpConversion>(context);
+ ExactlyOnceOpConversion, NoReassocOpConversion,
+ SetLengthOpConversion, ShapeOfOpConversion,
+ GetLengthOpConversion>(context);
patterns.insert<ElementalOpConversion>(context, optimizeEmptyElementals);
mlir::ConversionTarget target(*context);
// Note that YieldElementOp is not marked as an illegal operation.
@@ -909,7 +947,8 @@ class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase<BufferizeHLFIR> {
// survives this pass, the verifier will detect it because it has to be
// a child of ElementalOp and ElementalOp's are explicitly illegal.
target.addIllegalOp<hlfir::ApplyOp, hlfir::AssociateOp, hlfir::ElementalOp,
- hlfir::EndAssociateOp, hlfir::SetLengthOp>();
+ hlfir::EndAssociateOp, hlfir::ExactlyOnceOp,
+ hlfir::SetLengthOp>();
target.markUnknownOpDynamicallyLegal([](mlir::Operation *op) {
return llvm::all_of(op->getResultTypes(),
diff --git a/flang/test/HLFIR/bufferize-exactly_once.f90 b/flang/test/HLFIR/bufferize-exactly_once.f90
new file mode 100644
index 0000000000000..be97a70113653
--- /dev/null
+++ b/flang/test/HLFIR/bufferize-exactly_once.f90
@@ -0,0 +1,20 @@
+! RUN: bbc -emit-hlfir %s -o - | FileCheck %s
+
+program main
+ call test06()
+ print *,'pass'
+end program main
+
+subroutine test06()
+ type ty1
+ integer ,allocatable :: a(:,:,:)
+ end type ty1
+ type(ty1) :: str(1)
+ integer ,allocatable :: b(:,:,:)
+ allocate(str(1)%a(1,1,1),b(1,1,1))
+ b=1
+ write(6,*) "b = ", b
+ write(6,*) "reshape((/(b,jj=1,1)/),(/1,1,1/)) = ", reshape((/(b,jj=1,1)/),(/1,1,1/))
+ where ((/.true./)) str=(/(ty1(reshape((/(b,jj=1,1)/),(/1,1,1/))),ii=1,1)/)
+ ! CHECK: hlfir.exactly_once : !hlfir.expr<1x1x1xi32>
+end subroutine test06
``````````
</details>
https://github.com/llvm/llvm-project/pull/152202
More information about the flang-commits
mailing list