[flang-commits] [flang] 88ed439 - [flang][hlfir] Add ordered assignment pass with TODOs

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri May 5 00:22:20 PDT 2023


Author: Jean Perier
Date: 2023-05-05T09:21:43+02:00
New Revision: 88ed439562e95c936a8c6d06aa1405ae05792b40

URL: https://github.com/llvm/llvm-project/commit/88ed439562e95c936a8c6d06aa1405ae05792b40
DIFF: https://github.com/llvm/llvm-project/commit/88ed439562e95c936a8c6d06aa1405ae05792b40.diff

LOG: [flang][hlfir] Add ordered assignment pass with TODOs

I plan to implement lowering from parse tree to HLFIR first for forall
and where to ease testing of the rewrite pass while writing it.

To avoid cryptic errors in ConvertToFir pass about unhandled operations,
this patch already defines the pass that will further lower these
operations and make it throw clear TODO messages.

Differential Revision: https://reviews.llvm.org/D149852

Added: 
    flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
    flang/test/HLFIR/ordered-assignments-codegen-todo.fir

Modified: 
    flang/include/flang/Optimizer/HLFIR/Passes.h
    flang/include/flang/Optimizer/HLFIR/Passes.td
    flang/include/flang/Tools/CLOptions.inc
    flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
    flang/test/Driver/mlir-debug-pass-pipeline.f90
    flang/test/Driver/mlir-pass-pipeline.f90
    flang/test/Fir/basic-program.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h
index a82caeb61e3c3..a5aa35b92ae59 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.h
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.h
@@ -26,6 +26,7 @@ std::unique_ptr<mlir::Pass> createConvertHLFIRtoFIRPass();
 std::unique_ptr<mlir::Pass> createBufferizeHLFIRPass();
 std::unique_ptr<mlir::Pass> createLowerHLFIRIntrinsicsPass();
 std::unique_ptr<mlir::Pass> createSimplifyHLFIRIntrinsicsPass();
+std::unique_ptr<mlir::Pass> createLowerHLFIROrderedAssignmentsPass();
 
 #define GEN_PASS_REGISTRATION
 #include "flang/Optimizer/HLFIR/Passes.h.inc"

diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td
index a249a59ff442d..e2cf8447dff47 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.td
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.td
@@ -25,6 +25,11 @@ def LowerHLFIRIntrinsics : Pass<"lower-hlfir-intrinsics", "::mlir::ModuleOp"> {
   let constructor = "hlfir::createLowerHLFIRIntrinsicsPass()";
 }
 
+def LowerHLFIROrderedAssignments : Pass<"lower-hlfir-ordered-assignments", "::mlir::ModuleOp"> {
+  let summary = "Lower HLFIR ordered assignments like forall and where operations";
+  let constructor = "hlfir::createLowerHLFIROrderedAssignmentsPass()";
+}
+
 def SimplifyHLFIRIntrinsics : Pass<"simplify-hlfir-intrinsics", "::mlir::func::FuncOp"> {
   let summary = "Simplify HLFIR intrinsic operations that don't need to result in runtime calls";
   let constructor = "hlfir::createSimplifyHLFIRIntrinsicsPass()";

diff  --git a/flang/include/flang/Tools/CLOptions.inc b/flang/include/flang/Tools/CLOptions.inc
index 93285bb4c258d..a799427f023e4 100644
--- a/flang/include/flang/Tools/CLOptions.inc
+++ b/flang/include/flang/Tools/CLOptions.inc
@@ -242,6 +242,7 @@ inline void createHLFIRToFIRPassPipeline(
     addCanonicalizerPassWithoutRegionSimplification(pm);
     pm.addPass(hlfir::createSimplifyHLFIRIntrinsicsPass());
   }
+  pm.addPass(hlfir::createLowerHLFIROrderedAssignmentsPass());
   pm.addPass(hlfir::createLowerHLFIRIntrinsicsPass());
   pm.addPass(hlfir::createBufferizeHLFIRPass());
   pm.addPass(hlfir::createConvertHLFIRtoFIRPass());

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
index 03b135c345ef5..df2e2bd68f4ed 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
@@ -4,6 +4,7 @@ add_flang_library(HLFIRTransforms
   BufferizeHLFIR.cpp
   ConvertToFIR.cpp
   LowerHLFIRIntrinsics.cpp
+  LowerHLFIROrderedAssignments.cpp
   SimplifyHLFIRIntrinsics.cpp
 
   DEPENDS

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
new file mode 100644
index 0000000000000..85e32ffa0ec2d
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIROrderedAssignments.cpp
@@ -0,0 +1,106 @@
+//===- LowerHLFIROrderedAssignments.cpp - Lower HLFIR ordered assignments -===//
+//
+// 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 ordered assignments.
+// Ordered assignments are all the operations with the
+// OrderedAssignmentTreeOpInterface that implements user defined assignments,
+// assignment to vector subscripted entities, and assignments inside forall and
+// where.
+// The pass lowers these operations to regular hlfir.assign, loops and, if
+// needed, introduces temporary storage to fulfill Fortran semantics.
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace hlfir {
+#define GEN_PASS_DEF_LOWERHLFIRORDEREDASSIGNMENTS
+#include "flang/Optimizer/HLFIR/Passes.h.inc"
+} // namespace hlfir
+
+using namespace mlir;
+
+namespace {
+
+class ForallOpConversion : public mlir::OpRewritePattern<hlfir::ForallOp> {
+public:
+  explicit ForallOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}
+
+  mlir::LogicalResult
+  matchAndRewrite(hlfir::ForallOp forallOp,
+                  mlir::PatternRewriter &rewriter) const override {
+    TODO(forallOp.getLoc(), "FORALL construct or statement in HLFIR");
+    return mlir::failure();
+  }
+};
+
+class WhereOpConversion : public mlir::OpRewritePattern<hlfir::WhereOp> {
+public:
+  explicit WhereOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}
+
+  mlir::LogicalResult
+  matchAndRewrite(hlfir::WhereOp whereOp,
+                  mlir::PatternRewriter &rewriter) const override {
+    TODO(whereOp.getLoc(), "WHERE construct or statement in HLFIR");
+    return mlir::failure();
+  }
+};
+
+class RegionAssignConversion
+    : public mlir::OpRewritePattern<hlfir::RegionAssignOp> {
+public:
+  explicit RegionAssignConversion(mlir::MLIRContext *ctx)
+      : OpRewritePattern{ctx} {}
+
+  mlir::LogicalResult
+  matchAndRewrite(hlfir::RegionAssignOp regionAssignOp,
+                  mlir::PatternRewriter &rewriter) const override {
+    if (!regionAssignOp.getUserDefinedAssignment().empty())
+      TODO(regionAssignOp.getLoc(), "user defined assignment in HLFIR");
+    else
+      TODO(regionAssignOp.getLoc(),
+           "assignments to vector subscripted entity in HLFIR");
+    return mlir::failure();
+  }
+};
+
+class LowerHLFIROrderedAssignments
+    : public hlfir::impl::LowerHLFIROrderedAssignmentsBase<
+          LowerHLFIROrderedAssignments> {
+public:
+  void runOnOperation() override {
+    // Running on a ModuleOp because this pass may generate FuncOp declaration
+    // for runtime calls. This could be a FuncOp pass otherwise.
+    auto module = this->getOperation();
+    auto *context = &getContext();
+    mlir::RewritePatternSet patterns(context);
+    // Patterns are only defined for the OrderedAssignmentTreeOpInterface
+    // operations that can be the root of ordered assignments. The other
+    // operations will be taken care of while rewriting these trees (they
+    // cannot exist outside of these operations given their verifiers/traits).
+    patterns
+        .insert<ForallOpConversion, WhereOpConversion, RegionAssignConversion>(
+            context);
+    mlir::ConversionTarget target(*context);
+    target.markUnknownOpDynamicallyLegal([](mlir::Operation *op) {
+      return !mlir::isa<hlfir::OrderedAssignmentTreeOpInterface>(op);
+    });
+    if (mlir::failed(mlir::applyPartialConversion(module, target,
+                                                  std::move(patterns)))) {
+      mlir::emitError(mlir::UnknownLoc::get(context),
+                      "failure in HLFIR ordered assignments lowering pass");
+      signalPassFailure();
+    }
+  }
+};
+} // namespace
+
+std::unique_ptr<mlir::Pass> hlfir::createLowerHLFIROrderedAssignmentsPass() {
+  return std::make_unique<LowerHLFIROrderedAssignments>();
+}

diff  --git a/flang/test/Driver/mlir-debug-pass-pipeline.f90 b/flang/test/Driver/mlir-debug-pass-pipeline.f90
index d397b29bb56b2..320f06a854b34 100644
--- a/flang/test/Driver/mlir-debug-pass-pipeline.f90
+++ b/flang/test/Driver/mlir-debug-pass-pipeline.f90
@@ -25,6 +25,7 @@
 ! ALL: Pass statistics report
 
 ! ALL: Fortran::lower::VerifierPass
+! ALL-NEXT: LowerHLFIROrderedAssignments
 ! ALL-NEXT: LowerHLFIRIntrinsics
 ! ALL-NEXT: BufferizeHLFIR
 ! ALL-NEXT: ConvertHLFIRtoFIR

diff  --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90
index 9b0fa1ad5107e..44d253a467bb4 100644
--- a/flang/test/Driver/mlir-pass-pipeline.f90
+++ b/flang/test/Driver/mlir-pass-pipeline.f90
@@ -15,6 +15,7 @@
 ! O2-NEXT: Canonicalizer
 ! O2-NEXT: 'func.func' Pipeline
 ! O2-NEXT:   SimplifyHLFIRIntrinsics
+! ALL-NEXT: LowerHLFIROrderedAssignments
 ! ALL-NEXT: LowerHLFIRIntrinsics
 ! ALL-NEXT: BufferizeHLFIR
 ! ALL-NEXT: ConvertHLFIRtoFIR

diff  --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir
index a4f79e347b089..e6d849c2f4659 100644
--- a/flang/test/Fir/basic-program.fir
+++ b/flang/test/Fir/basic-program.fir
@@ -19,6 +19,7 @@ func.func @_QQmain() {
 // PASSES:        Canonicalizer
 // PASSES-NEXT: 'func.func' Pipeline
 // PASSES-NEXT:   SimplifyHLFIRIntrinsics
+// PASSES-NEXT:   LowerHLFIROrderedAssignments
 // PASSES-NEXT:   LowerHLFIRIntrinsics
 // PASSES-NEXT:   BufferizeHLFIR
 // PASSES-NEXT:   ConvertHLFIRtoFIR

diff  --git a/flang/test/HLFIR/ordered-assignments-codegen-todo.fir b/flang/test/HLFIR/ordered-assignments-codegen-todo.fir
new file mode 100644
index 0000000000000..ccbd97ce5caba
--- /dev/null
+++ b/flang/test/HLFIR/ordered-assignments-codegen-todo.fir
@@ -0,0 +1,24 @@
+// Just test that Ordered assignment pass TODOs are properly reported.
+// RUN: %not_todo_cmd fir-opt --lower-hlfir-ordered-assignments %s 2>&1 | FileCheck %s
+
+
+// CHECK: not yet implemented: FORALL construct or statement in HLFIR
+
+func.func @forall_todo(%arg0: !fir.ref<!fir.array<10xf32>>, %arg1: !fir.ref<!fir.array<10xf32>>) {
+  %c1 = arith.constant 1 : index
+  %c10 = arith.constant 10 : index
+  hlfir.forall lb {
+    hlfir.yield %c1 : index
+  } ub {
+    hlfir.yield %c10 : index
+  }  (%arg2: i64) {
+    hlfir.region_assign {
+      %1 = hlfir.designate %arg1 (%arg2)  : (!fir.ref<!fir.array<10xf32>>, i64) -> !fir.ref<f32>
+      hlfir.yield %1 : !fir.ref<f32>
+    } to {
+      %1 = hlfir.designate %arg0 (%arg2)  : (!fir.ref<!fir.array<10xf32>>, i64) -> !fir.ref<f32>
+      hlfir.yield %1 : !fir.ref<f32>
+    }
+  }
+  return
+}


        


More information about the flang-commits mailing list