[flang-commits] [flang] 451b1b1 - [flang] Add High level Fortran IR dialect

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Oct 21 04:11:51 PDT 2022


Author: Jean Perier
Date: 2022-10-21T13:11:13+02:00
New Revision: 451b1b1ffbb655fdebaea5bc2a508d60e16ca22e

URL: https://github.com/llvm/llvm-project/commit/451b1b1ffbb655fdebaea5bc2a508d60e16ca22e
DIFF: https://github.com/llvm/llvm-project/commit/451b1b1ffbb655fdebaea5bc2a508d60e16ca22e.diff

LOG: [flang] Add High level Fortran IR dialect

This patch adds the basic dialect definition of the HLFIR dialect that
was described in https://reviews.llvm.org/D134285.

It adds the definition of the hlfir.expr type and related tests so that
it can be verified that the dialect is properly hooked up by the tools.

Operations will be added as progress is made in the expression
lowering update.

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

Added: 
    flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
    flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
    flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td
    flang/lib/Optimizer/HLFIR/CMakeLists.txt
    flang/lib/Optimizer/HLFIR/HLFIRDialect.cpp
    flang/test/HLFIR/expr-type.fir

Modified: 
    flang/include/flang/Optimizer/CMakeLists.txt
    flang/include/flang/Optimizer/Support/InitFIR.h
    flang/lib/Frontend/CMakeLists.txt
    flang/lib/Optimizer/CMakeLists.txt
    flang/tools/bbc/CMakeLists.txt
    flang/tools/fir-opt/CMakeLists.txt
    flang/tools/tco/CMakeLists.txt
    flang/unittests/Optimizer/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/CMakeLists.txt b/flang/include/flang/Optimizer/CMakeLists.txt
index 0fa521d5b9670..89e43a9ee8d62 100644
--- a/flang/include/flang/Optimizer/CMakeLists.txt
+++ b/flang/include/flang/Optimizer/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(CodeGen)
 add_subdirectory(Dialect)
+add_subdirectory(HLFIR)
 add_subdirectory(Transforms)

diff  --git a/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt b/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
new file mode 100644
index 0000000000000..35fda6d1610ec
--- /dev/null
+++ b/flang/include/flang/Optimizer/HLFIR/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_TARGET_DEFINITIONS HLFIROpBase.td)
+mlir_tablegen(HLFIRTypes.h.inc -gen-typedef-decls)
+mlir_tablegen(HLFIRTypes.cpp.inc -gen-typedef-defs)
+mlir_tablegen(HLFIRDialect.h.inc -gen-dialect-decls -dialect=hlfir)
+mlir_tablegen(HLFIRDialect.cpp.inc -gen-dialect-defs -dialect=hlfir)
+mlir_tablegen(HLFIRAttributes.h.inc -gen-attrdef-decls -attrdefs-dialect=hlfir)
+mlir_tablegen(HLFIRAttributes.cpp.inc -gen-attrdef-defs -attrdefs-dialect=hlfir)
+add_public_tablegen_target(HLFIROpsIncGen)

diff  --git a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
new file mode 100644
index 0000000000000..2e7f615065abd
--- /dev/null
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
@@ -0,0 +1,27 @@
+//===- HLFIRDialect.h - High Level Fortran IR dialect -----------*- 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 file defines the HLFIR dialect that models Fortran expressions and
+// assignments without requiring storage allocation and manipulations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_HLFIR_HLFIRDIALECT_H
+#define FORTRAN_OPTIMIZER_HLFIR_HLFIRDIALECT_H
+
+#include "mlir/IR/Dialect.h"
+
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "flang/Optimizer/HLFIR/HLFIRTypes.h.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "flang/Optimizer/HLFIR/HLFIRAttributes.h.inc"
+
+#endif // FORTRAN_OPTIMIZER_HLFIR_HLFIRDIALECT_H

diff  --git a/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td b/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td
new file mode 100644
index 0000000000000..9b3578c406847
--- /dev/null
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROpBase.td
@@ -0,0 +1,73 @@
+//===-- HLFIROpBase.td - HLFIR dialect base definitions ----*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of the HLFIR dialect and core hlfir.expr type
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_DIALECT_HLFIR_OP_BASE
+#define FORTRAN_DIALECT_HLFIR_OP_BASE
+
+include "mlir/IR/AttrTypeBase.td"
+include "mlir/IR/OpBase.td"
+
+def hlfir_Dialect : Dialect {
+  let name = "hlfir";
+
+  let summary = "High Level Fortran IR.";
+
+  let description = [{
+    This dialect models Fortran expressions and assignments without requiring
+    the allocation and manipulation of temporary storage.
+    It allows running high level optimization passes and is rather
+    straightforward to generate from Fortran expressions and assignments.
+
+    It is not a complete implementation of Fortran, for constructs and lower
+    level operations, FIR should be used directly.
+
+    A bufferization pass transforms hlfir.expr values into FIR temporary in
+    memory, and its translation pass to FIR translates high level operations
+    into sequence of lower level FIR operations operating on memory.
+  }];
+
+  let useDefaultTypePrinterParser = 1;
+  let cppNamespace = "hlfir";
+}
+
+
+def hlfir_ExprType : TypeDef<hlfir_Dialect, "Expr"> {
+  let mnemonic = "expr";
+  let summary = "The type of an array, character, or derived type Fortran expression";
+
+  let description = [{
+    Abstract value type for Fortran arrays, characters and derived types.
+    The rank cannot be assumed, and empty shape means that the expression is a scalar.
+    When the element type is a derived type, the polymorphic flag may be set to true
+    to indicate that the expression dynamic type can 
diff er from its static type.
+  }];
+
+
+  let parameters = (ins
+    ArrayRefParameter<"int64_t", "expression shape">:$shape,
+    "mlir::Type":$elementType,
+    "bool":$polymorphic
+  );
+
+  let extraClassDeclaration = [{
+    using Shape = llvm::SmallVector<int64_t>;
+    mlir::Type getEleTy() const {return getElementType();}
+    bool isArray() const { return !getShape().empty(); }
+    bool isPolymorphic() const { return getPolymorphic(); }
+  }];
+
+  let hasCustomAssemblyFormat = 1;
+
+}
+
+#endif // FORTRAN_DIALECT_HLFIR_OP_BASE

diff  --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h
index 77344f7407909..434556edb32ee 100644
--- a/flang/include/flang/Optimizer/Support/InitFIR.h
+++ b/flang/include/flang/Optimizer/Support/InitFIR.h
@@ -14,6 +14,7 @@
 #define FORTRAN_OPTIMIZER_SUPPORT_INITFIR_H
 
 #include "flang/Optimizer/Dialect/FIRDialect.h"
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
 #include "mlir/Conversion/Passes.h"
 #include "mlir/Dialect/Affine/Passes.h"
 #include "mlir/InitAllDialects.h"
@@ -25,11 +26,11 @@
 namespace fir::support {
 
 #define FLANG_NONCODEGEN_DIALECT_LIST                                          \
-  mlir::AffineDialect, FIROpsDialect, mlir::acc::OpenACCDialect,               \
-      mlir::omp::OpenMPDialect, mlir::scf::SCFDialect,                         \
-      mlir::arith::ArithDialect, mlir::cf::ControlFlowDialect,                 \
-      mlir::func::FuncDialect, mlir::vector::VectorDialect,                    \
-      mlir::math::MathDialect
+  mlir::AffineDialect, FIROpsDialect, hlfir::hlfirDialect,                     \
+      mlir::acc::OpenACCDialect, mlir::omp::OpenMPDialect,                     \
+      mlir::scf::SCFDialect, mlir::arith::ArithDialect,                        \
+      mlir::cf::ControlFlowDialect, mlir::func::FuncDialect,                   \
+      mlir::vector::VectorDialect, mlir::math::MathDialect
 
 // The definitive list of dialects used by flang.
 #define FLANG_DIALECT_LIST                                                     \

diff  --git a/flang/lib/Frontend/CMakeLists.txt b/flang/lib/Frontend/CMakeLists.txt
index 96769c707f102..fbe3024479806 100644
--- a/flang/lib/Frontend/CMakeLists.txt
+++ b/flang/lib/Frontend/CMakeLists.txt
@@ -17,6 +17,7 @@ add_flang_library(flangFrontend
   FIRDialect
   FIRSupport
   FIROptTransformsPassIncGen
+  HLFIRDialect
   MLIRIR
   ${dialect_libs}
 
@@ -33,6 +34,7 @@ add_flang_library(flangFrontend
   FIRBuilder
   FIRCodeGen
   FIRTransforms
+  HLFIRDialect
   MLIRTransforms
   MLIRLLVMToLLVMIRTranslation
   MLIRSCFToControlFlow

diff  --git a/flang/lib/Optimizer/CMakeLists.txt b/flang/lib/Optimizer/CMakeLists.txt
index d2da0f98611a1..2320bf4f44270 100644
--- a/flang/lib/Optimizer/CMakeLists.txt
+++ b/flang/lib/Optimizer/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_subdirectory(Builder)
 add_subdirectory(CodeGen)
 add_subdirectory(Dialect)
+add_subdirectory(HLFIR)
 add_subdirectory(Support)
 add_subdirectory(Transforms)

diff  --git a/flang/lib/Optimizer/HLFIR/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/CMakeLists.txt
new file mode 100644
index 0000000000000..890bc52cc8453
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/CMakeLists.txt
@@ -0,0 +1,20 @@
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_flang_library(HLFIRDialect
+  HLFIRDialect.cpp
+
+  DEPENDS
+  FIRDialect
+  HLFIROpsIncGen
+  ${dialect_libs}
+
+  LINK_LIBS
+  FIRDialect
+  MLIRIR
+  ${dialect_libs}
+
+  LINK_COMPONENTS
+  AsmParser
+  AsmPrinter
+  Remarks
+)

diff  --git a/flang/lib/Optimizer/HLFIR/HLFIRDialect.cpp b/flang/lib/Optimizer/HLFIR/HLFIRDialect.cpp
new file mode 100644
index 0000000000000..a6406992948ab
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/HLFIRDialect.cpp
@@ -0,0 +1,72 @@
+//===-- HLFIRDialect.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/Matchers.h"
+#include "mlir/IR/OpImplementation.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+#include "flang/Optimizer/HLFIR/HLFIRDialect.cpp.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "flang/Optimizer/HLFIR/HLFIRAttributes.cpp.inc"
+
+void hlfir::hlfirDialect::initialize() {
+  addTypes<
+#define GET_TYPEDEF_LIST
+#include "flang/Optimizer/HLFIR/HLFIRTypes.cpp.inc"
+      >();
+}
+
+// `expr` `<` `*` | bounds (`x` bounds)* `:` type [`?`] `>`
+// bounds ::= `?` | int-lit
+mlir::Type hlfir::ExprType::parse(mlir::AsmParser &parser) {
+  if (parser.parseLess())
+    return {};
+  ExprType::Shape shape;
+  if (parser.parseOptionalStar()) {
+    if (parser.parseDimensionList(shape, /*allowDynamic=*/true))
+      return {};
+  } else if (parser.parseColon()) {
+    return {};
+  }
+  mlir::Type eleTy;
+  if (parser.parseType(eleTy))
+    return {};
+  const bool polymorphic = mlir::succeeded(parser.parseOptionalQuestion());
+  if (parser.parseGreater())
+    return {};
+  return ExprType::get(parser.getContext(), shape, eleTy, polymorphic);
+}
+
+void hlfir::ExprType::print(mlir::AsmPrinter &printer) const {
+  auto shape = getShape();
+  printer << '<';
+  if (shape.size()) {
+    for (const auto &b : shape) {
+      if (b >= 0)
+        printer << b << 'x';
+      else
+        printer << "?x";
+    }
+  }
+  printer << getEleTy();
+  if (isPolymorphic())
+    printer << '?';
+  printer << '>';
+}

diff  --git a/flang/test/HLFIR/expr-type.fir b/flang/test/HLFIR/expr-type.fir
new file mode 100644
index 0000000000000..835959ce54643
--- /dev/null
+++ b/flang/test/HLFIR/expr-type.fir
@@ -0,0 +1,31 @@
+// Test the HLFIR Expr type
+// Parse types and check that we can reparse what we print.
+// RUN: fir-opt --split-input-file %s | fir-opt --split-input-file | FileCheck %s
+
+// Scalar expression types
+func.func private @scalar01() -> !hlfir.expr<!fir.char<1,?>>
+func.func private @scalar02() -> !hlfir.expr<!fir.char<2,10>>
+func.func private @scalar03() -> !hlfir.expr<!fir.type<derived{f:f32}>>
+// CHECK-LABEL:  func.func private @scalar01() -> !hlfir.expr<!fir.char<1,?>>
+// CHECK-LABEL:  func.func private @scalar02() -> !hlfir.expr<!fir.char<2,10>>
+// CHECK-LABEL:  func.func private @scalar03() -> !hlfir.expr<!fir.type<derived{f:f32}>>
+
+// Array expression types
+func.func private @array01() -> !hlfir.expr<?x!fir.char<1,?>>
+func.func private @array02() -> !hlfir.expr<10x!fir.char<1,20>>
+func.func private @array03() -> !hlfir.expr<10x?x20x?x30x?x40x?x50x?x60xf128>
+func.func private @array04() -> !hlfir.expr<10x20x!fir.type<derived{f:f32}>>
+func.func private @array05() -> !hlfir.expr<10xi32>
+// CHECK-LABEL:  func.func private @array01() -> !hlfir.expr<?x!fir.char<1,?>>
+// CHECK-LABEL:  func.func private @array02() -> !hlfir.expr<10x!fir.char<1,20>>
+// CHECK-LABEL:  func.func private @array03() -> !hlfir.expr<10x?x20x?x30x?x40x?x50x?x60xf128>
+// CHECK-LABEL:  func.func private @array04() -> !hlfir.expr<10x20x!fir.type<derived{f:f32}>>
+// CHECK-LABEL:  func.func private @array05() -> !hlfir.expr<10xi32>
+
+// Polymorphic expression types
+func.func private @polymorph01() -> !hlfir.expr<!fir.type<derived{f:f32}>?>
+func.func private @polymorph02() -> !hlfir.expr<?x!fir.type<derived{f:f32}>?>
+func.func private @polymorph03() -> !hlfir.expr<10x!fir.type<derived{f:f32}>?>
+// CHECK-LABEL:  func.func private @polymorph01() -> !hlfir.expr<!fir.type<derived{f:f32}>?>
+// CHECK-LABEL:  func.func private @polymorph02() -> !hlfir.expr<?x!fir.type<derived{f:f32}>?>
+// CHECK-LABEL:  func.func private @polymorph03() -> !hlfir.expr<10x!fir.type<derived{f:f32}>?>

diff  --git a/flang/tools/bbc/CMakeLists.txt b/flang/tools/bbc/CMakeLists.txt
index 5830531dff78c..4c50d629197b1 100644
--- a/flang/tools/bbc/CMakeLists.txt
+++ b/flang/tools/bbc/CMakeLists.txt
@@ -11,6 +11,7 @@ FIRDialect
 FIRSupport
 FIRTransforms
 FIRBuilder
+HLFIRDialect
 ${dialect_libs}
 MLIRAffineToStandard
 MLIRSCFToControlFlow

diff  --git a/flang/tools/fir-opt/CMakeLists.txt b/flang/tools/fir-opt/CMakeLists.txt
index 8bed259e049bd..adbdb23739dd0 100644
--- a/flang/tools/fir-opt/CMakeLists.txt
+++ b/flang/tools/fir-opt/CMakeLists.txt
@@ -7,6 +7,7 @@ target_link_libraries(fir-opt PRIVATE
   FIRSupport
   FIRTransforms
   FIRCodeGen
+  HLFIRDialect
   ${dialect_libs}
 
   # TODO: these should be transitive dependencies from a target providing

diff  --git a/flang/tools/tco/CMakeLists.txt b/flang/tools/tco/CMakeLists.txt
index 329c3864f3fe5..e78124996b7d7 100644
--- a/flang/tools/tco/CMakeLists.txt
+++ b/flang/tools/tco/CMakeLists.txt
@@ -7,6 +7,7 @@ target_link_libraries(tco PRIVATE
   FIRSupport
   FIRTransforms
   FIRBuilder
+  HLFIRDialect
   ${dialect_libs}
   MLIRIR
   MLIRLLVMDialect

diff  --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt
index e23f0cfe39eee..c3cc04e86ce2d 100644
--- a/flang/unittests/Optimizer/CMakeLists.txt
+++ b/flang/unittests/Optimizer/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LIBS
   FIRCodeGen
   FIRDialect
   FIRSupport
+  HLFIRDialect
   ${dialect_libs}
 )
 


        


More information about the flang-commits mailing list