diff --git a/flang/include/flang/Lower/DoLoopHelper.h b/flang/include/flang/Lower/DoLoopHelper.h new file mode 100644 --- /dev/null +++ b/flang/include/flang/Lower/DoLoopHelper.h @@ -0,0 +1,45 @@ +//===-- Lower/DoLoopHelper.h -- gen fir.do_loop ops -------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef FORTRAN_LOWER_DOLOOPHELPER_H +#define FORTRAN_LOWER_DOLOOPHELPER_H + +#include "flang/Lower/FIRBuilder.h" + +namespace Fortran::lower { + +/// Helper to build fir.do_loop Ops. +class DoLoopHelper { +public: + explicit DoLoopHelper(FirOpBuilder &builder, mlir::Location loc) + : builder(builder), loc(loc) {} + DoLoopHelper(const DoLoopHelper &) = delete; + + /// Type of a callback to generate the loop body. + using BodyGenerator = std::function; + + /// Build loop [\p lb, \p ub] with step \p step. + /// If \p step is an empty value, 1 is used for the step. + void createLoop(mlir::Value lb, mlir::Value ub, mlir::Value step, + const BodyGenerator &bodyGenerator); + + /// Build loop [\p lb, \p ub] with step 1. + void createLoop(mlir::Value lb, mlir::Value ub, + const BodyGenerator &bodyGenerator); + + /// Build loop [0, \p count) with step 1. + void createLoop(mlir::Value count, const BodyGenerator &bodyGenerator); + +private: + FirOpBuilder &builder; + mlir::Location loc; +}; + +} // namespace Fortran::lower + +#endif // FORTRAN_LOWER_DOLOOPHELPER_H diff --git a/flang/lib/Lower/CMakeLists.txt b/flang/lib/Lower/CMakeLists.txt --- a/flang/lib/Lower/CMakeLists.txt +++ b/flang/lib/Lower/CMakeLists.txt @@ -1,11 +1,18 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error -Wno-unused-parameter") add_flang_library(FortranLower - ConvertType.cpp ComplexExpr.cpp + ConvertType.cpp + DoLoopHelper.cpp OpenMP.cpp PFTBuilder.cpp + DEPENDS + FIROpsIncGen + MLIROpAsmInterfaceIncGen + MLIRControlFlowInterfaces + MLIRLinalgStructuredOpsInterfaceIncGen + LINK_COMPONENTS Support ) diff --git a/flang/lib/Lower/DoLoopHelper.cpp b/flang/lib/Lower/DoLoopHelper.cpp new file mode 100644 --- /dev/null +++ b/flang/lib/Lower/DoLoopHelper.cpp @@ -0,0 +1,44 @@ +//===-- DoLoopHelper.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/DoLoopHelper.h" + +//===----------------------------------------------------------------------===// +// DoLoopHelper implementation +//===----------------------------------------------------------------------===// + +void Fortran::lower::DoLoopHelper::createLoop( + mlir::Value lb, mlir::Value ub, mlir::Value step, + const BodyGenerator &bodyGenerator) { + auto lbi = builder.convertToIndexType(loc, lb); + auto ubi = builder.convertToIndexType(loc, ub); + assert(step && "step must be an actual Value"); + auto inc = builder.convertToIndexType(loc, step); + auto loop = builder.create(loc, lbi, ubi, inc); + auto insertPt = builder.saveInsertionPoint(); + builder.setInsertionPointToStart(loop.getBody()); + auto index = loop.getInductionVar(); + bodyGenerator(builder, index); + builder.restoreInsertionPoint(insertPt); +} + +void Fortran::lower::DoLoopHelper::createLoop( + mlir::Value lb, mlir::Value ub, const BodyGenerator &bodyGenerator) { + createLoop(lb, ub, + builder.createIntegerConstant(loc, builder.getIndexType(), 1), + bodyGenerator); +} + +void Fortran::lower::DoLoopHelper::createLoop( + mlir::Value count, const BodyGenerator &bodyGenerator) { + auto indexType = builder.getIndexType(); + auto zero = builder.createIntegerConstant(loc, indexType, 0); + auto one = builder.createIntegerConstant(loc, count.getType(), 1); + auto up = builder.create(loc, count, one); + createLoop(zero, up, one, bodyGenerator); +}