[flang-commits] [flang] aab4263 - [flang] Lower basic STOP statement

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Tue Feb 1 11:54:57 PST 2022


Author: Valentin Clement
Date: 2022-02-01T20:54:45+01:00
New Revision: aab4263ad66c99da15cb9bda6aec8269d159b113

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

LOG: [flang] Lower basic STOP statement

This patch lowers STOP statement without arguments
and ERROR STOP. STOP statement with arguments lowering will
come in later patches ince it requires some expression lowering
to be added.
STOP statement is lowered to a runtime call.

Also makes sure we are creating a constant in the MLIR arith constant.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: kiranchandramohan, schweitz

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

Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>

Added: 
    flang/lib/Lower/Runtime.cpp
    flang/test/Lower/stop-statement.f90

Modified: 
    flang/lib/Lower/Bridge.cpp
    flang/lib/Lower/CMakeLists.txt
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp
    flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index fdd422586690e..fd52a76cf2f65 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -15,6 +15,7 @@
 #include "flang/Lower/CallInterface.h"
 #include "flang/Lower/Mangler.h"
 #include "flang/Lower/PFTBuilder.h"
+#include "flang/Lower/Runtime.h"
 #include "flang/Lower/SymbolMap.h"
 #include "flang/Lower/Todo.h"
 #include "flang/Optimizer/Support/FIRContext.h"
@@ -553,8 +554,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     TODO(toLocation(), "FailImageStmt lowering");
   }
 
+  // call STOP, ERROR STOP in runtime
   void genFIR(const Fortran::parser::StopStmt &stmt) {
-    TODO(toLocation(), "StopStmt lowering");
+    genStopStatement(*this, stmt);
   }
 
   void genFIR(const Fortran::parser::ReturnStmt &stmt) {

diff  --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt
index 9981f5d2b8bca..925ac0acfe2b6 100644
--- a/flang/lib/Lower/CMakeLists.txt
+++ b/flang/lib/Lower/CMakeLists.txt
@@ -9,6 +9,7 @@ add_flang_library(FortranLower
   OpenACC.cpp
   OpenMP.cpp
   PFTBuilder.cpp
+  Runtime.cpp
   SymbolMap.cpp
 
   DEPENDS

diff  --git a/flang/lib/Lower/Runtime.cpp b/flang/lib/Lower/Runtime.cpp
new file mode 100644
index 0000000000000..7156a8851f1dc
--- /dev/null
+++ b/flang/lib/Lower/Runtime.cpp
@@ -0,0 +1,70 @@
+//===-- Runtime.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Lower/Runtime.h"
+#include "flang/Lower/Bridge.h"
+#include "flang/Lower/Todo.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
+#include "flang/Parser/parse-tree.h"
+#include "flang/Runtime/stop.h"
+#include "flang/Semantics/tools.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "flang-lower-runtime"
+
+using namespace Fortran::runtime;
+
+/// Runtime calls that do not return to the caller indicate this condition by
+/// terminating the current basic block with an unreachable op.
+static void genUnreachable(fir::FirOpBuilder &builder, mlir::Location loc) {
+  builder.create<fir::UnreachableOp>(loc);
+  mlir::Block *newBlock =
+      builder.getBlock()->splitBlock(builder.getInsertionPoint());
+  builder.setInsertionPointToStart(newBlock);
+}
+
+//===----------------------------------------------------------------------===//
+// Misc. Fortran statements that lower to runtime calls
+//===----------------------------------------------------------------------===//
+
+void Fortran::lower::genStopStatement(
+    Fortran::lower::AbstractConverter &converter,
+    const Fortran::parser::StopStmt &stmt) {
+  fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  mlir::Location loc = converter.getCurrentLocation();
+  llvm::SmallVector<mlir::Value> operands;
+  mlir::FuncOp callee;
+  mlir::FunctionType calleeType;
+  // First operand is stop code (zero if absent)
+  if (std::get<std::optional<Fortran::parser::StopCode>>(stmt.t)) {
+    TODO(loc, "STOP first operand not lowered yet");
+  } else {
+    callee = fir::runtime::getRuntimeFunc<mkRTKey(StopStatement)>(loc, builder);
+    calleeType = callee.getType();
+    operands.push_back(
+        builder.createIntegerConstant(loc, calleeType.getInput(0), 0));
+  }
+
+  // Second operand indicates ERROR STOP
+  bool isError = std::get<Fortran::parser::StopStmt::Kind>(stmt.t) ==
+                 Fortran::parser::StopStmt::Kind::ErrorStop;
+  operands.push_back(builder.createIntegerConstant(
+      loc, calleeType.getInput(operands.size()), isError));
+
+  // Third operand indicates QUIET (default to false).
+  if (std::get<std::optional<Fortran::parser::ScalarLogicalExpr>>(stmt.t)) {
+    TODO(loc, "STOP third operand not lowered yet");
+  } else {
+    operands.push_back(builder.createIntegerConstant(
+        loc, calleeType.getInput(operands.size()), 0));
+  }
+
+  builder.create<fir::CallOp>(loc, callee, operands);
+  genUnreachable(builder, loc);
+}

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index b9a9316325adc..ac56e32c4e00f 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -80,7 +80,7 @@ mlir::Value fir::FirOpBuilder::createNullConstant(mlir::Location loc,
 mlir::Value fir::FirOpBuilder::createIntegerConstant(mlir::Location loc,
                                                      mlir::Type ty,
                                                      std::int64_t cst) {
-  return create<mlir::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
+  return create<mlir::arith::ConstantOp>(loc, ty, getIntegerAttr(ty, cst));
 }
 
 mlir::Value

diff  --git a/flang/test/Lower/stop-statement.f90 b/flang/test/Lower/stop-statement.f90
new file mode 100644
index 0000000000000..497b6db1a9f4b
--- /dev/null
+++ b/flang/test/Lower/stop-statement.f90
@@ -0,0 +1,21 @@
+! RUN: bbc %s -emit-fir --canonicalize -o - | FileCheck %s
+
+! CHECK-LABEL stop_test
+subroutine stop_test()
+ ! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : i32
+ ! CHECK-DAG: %[[false:.*]] = arith.constant false
+ ! CHECK: fir.call @_Fortran{{.*}}StopStatement(%[[c0]], %[[false]], %[[false]])
+ ! CHECK-NEXT: fir.unreachable
+ stop
+end subroutine 
+
+
+! CHECK-LABEL stop_error
+subroutine stop_error()
+ error stop
+ ! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : i32
+ ! CHECK-DAG: %[[true:.*]] = arith.constant true
+ ! CHECK-DAG: %[[false:.*]] = arith.constant false
+ ! CHECK: fir.call @_Fortran{{.*}}StopStatement(%[[c0]], %[[true]], %[[false]])
+ ! CHECK-NEXT: fir.unreachable
+end subroutine

diff  --git a/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp b/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp
index 348438238a7ae..0808c4eb5d3bd 100644
--- a/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp
+++ b/flang/unittests/Optimizer/Builder/DoLoopHelperTest.cpp
@@ -30,8 +30,8 @@ struct DoLoopHelperTest : public testing::Test {
 };
 
 void checkConstantValue(const mlir::Value &value, int64_t v) {
-  EXPECT_TRUE(mlir::isa<ConstantOp>(value.getDefiningOp()));
-  auto cstOp = dyn_cast<ConstantOp>(value.getDefiningOp());
+  EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
+  auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
   auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
   EXPECT_EQ(v, valueAttr.getInt());
 }

diff  --git a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
index 6fb5c745bce21..7613d9145944a 100644
--- a/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
+++ b/flang/unittests/Optimizer/Builder/FIRBuilderTest.cpp
@@ -48,8 +48,8 @@ static arith::CmpIOp createCondition(fir::FirOpBuilder &builder) {
 }
 
 static void checkIntegerConstant(mlir::Value value, mlir::Type ty, int64_t v) {
-  EXPECT_TRUE(mlir::isa<ConstantOp>(value.getDefiningOp()));
-  auto cstOp = dyn_cast<ConstantOp>(value.getDefiningOp());
+  EXPECT_TRUE(mlir::isa<mlir::arith::ConstantOp>(value.getDefiningOp()));
+  auto cstOp = dyn_cast<mlir::arith::ConstantOp>(value.getDefiningOp());
   EXPECT_EQ(ty, cstOp.getType());
   auto valueAttr = cstOp.getValue().dyn_cast_or_null<IntegerAttr>();
   EXPECT_EQ(v, valueAttr.getInt());


        


More information about the flang-commits mailing list