diff --git a/flang/include/flang/Optimizer/Builder/Runtime/Transformational.h b/flang/include/flang/Optimizer/Builder/Runtime/Transformational.h new file mode 100644 --- /dev/null +++ b/flang/include/flang/Optimizer/Builder/Runtime/Transformational.h @@ -0,0 +1,63 @@ +//===-- Transformational.h --------------------------------------*- C++ -*-===// +// Generate transformational intrinsic runtime API calls. +// +// 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_OPTIMIZER_BUILDER_RUNTIME_TRANSFORMATIONAL_H +#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_TRANSFORMATIONAL_H + +#include "mlir/Dialect/StandardOps/IR/Ops.h" + +namespace fir { +class ExtendedValue; +class FirOpBuilder; +} // namespace fir + +namespace fir::runtime { + +void genCshift(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox, mlir::Value dimBox); + +void genCshiftVector(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox); + +void genEoshift(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox, mlir::Value boundBox, mlir::Value dimBox); + +void genEoshiftVector(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox, mlir::Value boundBox); + +void genMatmul(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value matrixABox, mlir::Value matrixBBox, + mlir::Value resultBox); + +void genPack(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, mlir::Value maskBox, + mlir::Value vectorBox); + +void genReshape(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox, + mlir::Value shapeBox, mlir::Value padBox, mlir::Value orderBox); + +void genSpread(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox, mlir::Value dim, + mlir::Value ncopies); + +void genTranspose(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox); + +void genUnpack(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value vectorBox, + mlir::Value maskBox, mlir::Value fieldBox); + +} // namespace fir::runtime + +#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_TRANSFORMATIONAL_H diff --git a/flang/lib/Optimizer/Builder/CMakeLists.txt b/flang/lib/Optimizer/Builder/CMakeLists.txt --- a/flang/lib/Optimizer/Builder/CMakeLists.txt +++ b/flang/lib/Optimizer/Builder/CMakeLists.txt @@ -7,6 +7,7 @@ DoLoopHelper.cpp FIRBuilder.cpp MutableBox.cpp + Runtime/Transformational.cpp DEPENDS FIRDialect diff --git a/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp new file mode 100644 --- /dev/null +++ b/flang/lib/Optimizer/Builder/Runtime/Transformational.cpp @@ -0,0 +1,176 @@ +//===-- Transformational.cpp ------------------------------------*- C++ -*-===// +// Generate transformational intrinsic runtime API calls. +// +// 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/Optimizer/Builder/Runtime/Transformational.h" +#include "flang/Lower/Todo.h" +#include "flang/Optimizer/Builder/BoxValue.h" +#include "flang/Optimizer/Builder/Character.h" +#include "flang/Optimizer/Builder/FIRBuilder.h" +#include "flang/Optimizer/Builder/Runtime/RTBuilder.h" +#include "flang/Runtime/matmul.h" +#include "flang/Runtime/transformational.h" +#include "mlir/Dialect/StandardOps/IR/Ops.h" + +using namespace Fortran::runtime; + +/// Generate call to Cshift intrinsic +void fir::runtime::genCshift(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox, mlir::Value dimBox) { + auto cshiftFunc = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = cshiftFunc.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, + shiftBox, dimBox, sourceFile, sourceLine); + builder.create(loc, cshiftFunc, args); +} + +/// Generate call to the vector version of the Cshift intrinsic +void fir::runtime::genCshiftVector(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value resultBox, + mlir::Value arrayBox, mlir::Value shiftBox) { + auto cshiftFunc = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = cshiftFunc.getType(); + + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); + auto args = fir::runtime::createArguments( + builder, loc, fTy, resultBox, arrayBox, shiftBox, sourceFile, sourceLine); + builder.create(loc, cshiftFunc, args); +} + +/// Generate call to Eoshift intrinsic +void fir::runtime::genEoshift(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value shiftBox, mlir::Value boundBox, + mlir::Value dimBox) { + auto eoshiftFunc = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = eoshiftFunc.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(6)); + auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, + arrayBox, shiftBox, boundBox, + dimBox, sourceFile, sourceLine); + builder.create(loc, eoshiftFunc, args); +} + +/// Generate call to the vector version of the Eoshift intrinsic +void fir::runtime::genEoshiftVector(fir::FirOpBuilder &builder, + mlir::Location loc, mlir::Value resultBox, + mlir::Value arrayBox, mlir::Value shiftBox, + mlir::Value boundBox) { + auto eoshiftFunc = + fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = eoshiftFunc.getType(); + + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, + shiftBox, boundBox, sourceFile, sourceLine); + builder.create(loc, eoshiftFunc, args); +} + +/// Generate call to Matmul intrinsic runtime routine. +void fir::runtime::genMatmul(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value matrixABox, + mlir::Value matrixBBox) { + auto func = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(4)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, matrixABox, + matrixBBox, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +/// Generate call to Pack intrinsic runtime routine. +void fir::runtime::genPack(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value arrayBox, + mlir::Value maskBox, mlir::Value vectorBox) { + auto packFunc = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = packFunc.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, arrayBox, + maskBox, vectorBox, sourceFile, sourceLine); + builder.create(loc, packFunc, args); +} + +/// Generate call to Reshape intrinsic runtime routine. +void fir::runtime::genReshape(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox, + mlir::Value shapeBox, mlir::Value padBox, + mlir::Value orderBox) { + auto func = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(6)); + auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, + sourceBox, shapeBox, padBox, + orderBox, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +/// Generate call to Spread intrinsic runtime routine. +void fir::runtime::genSpread(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox, + mlir::Value dim, mlir::Value ncopies) { + auto func = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, sourceBox, + dim, ncopies, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +/// Generate call to Transpose intrinsic runtime routine. +void fir::runtime::genTranspose(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value sourceBox) { + auto func = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = func.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(3)); + auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox, + sourceBox, sourceFile, sourceLine); + builder.create(loc, func, args); +} + +/// Generate call to Unpack intrinsic runtime routine. +void fir::runtime::genUnpack(fir::FirOpBuilder &builder, mlir::Location loc, + mlir::Value resultBox, mlir::Value vectorBox, + mlir::Value maskBox, mlir::Value fieldBox) { + auto unpackFunc = fir::runtime::getRuntimeFunc(loc, builder); + auto fTy = unpackFunc.getType(); + auto sourceFile = fir::factory::locationToFilename(builder, loc); + auto sourceLine = + fir::factory::locationToLineNo(builder, loc, fTy.getInput(5)); + auto args = + fir::runtime::createArguments(builder, loc, fTy, resultBox, vectorBox, + maskBox, fieldBox, sourceFile, sourceLine); + builder.create(loc, unpackFunc, args); +} diff --git a/flang/unittests/Optimizer/Builder/Runtime/TransformationalTest.cpp b/flang/unittests/Optimizer/Builder/Runtime/TransformationalTest.cpp new file mode 100644 --- /dev/null +++ b/flang/unittests/Optimizer/Builder/Runtime/TransformationalTest.cpp @@ -0,0 +1,129 @@ +//===- TransformationalTest.cpp -- Transformational intrinsic generation --===// +// +// 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/Optimizer/Builder/Runtime/Transformational.h" +#include "RuntimeCallTestBase.h" +#include "gtest/gtest.h" + +TEST_F(RuntimeCallTest, genCshiftTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value array = firBuilder->create(loc, seqTy); + mlir::Value shift = firBuilder->create(loc, seqTy); + mlir::Value dim = firBuilder->create(loc, seqTy); + fir::runtime::genCshift(*firBuilder, loc, result, array, shift, dim); + checkCallOpFromResultBox(result, "_FortranACshift", 4); +} + +TEST_F(RuntimeCallTest, genCshiftVectorTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value array = firBuilder->create(loc, seqTy); + mlir::Value shift = firBuilder->create(loc, seqTy); + fir::runtime::genCshiftVector(*firBuilder, loc, result, array, shift); + checkCallOpFromResultBox(result, "_FortranACshiftVector", 3); +} + +TEST_F(RuntimeCallTest, genEoshiftTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value array = firBuilder->create(loc, seqTy); + mlir::Value shift = firBuilder->create(loc, seqTy); + mlir::Value bound = firBuilder->create(loc, seqTy); + mlir::Value dim = firBuilder->create(loc, seqTy); + fir::runtime::genEoshift(*firBuilder, loc, result, array, shift, bound, dim); + checkCallOpFromResultBox(result, "_FortranAEoshift", 5); +} + +TEST_F(RuntimeCallTest, genEoshiftVectorTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value array = firBuilder->create(loc, seqTy); + mlir::Value shift = firBuilder->create(loc, seqTy); + mlir::Value bound = firBuilder->create(loc, seqTy); + fir::runtime::genEoshiftVector(*firBuilder, loc, result, array, shift, bound); + checkCallOpFromResultBox(result, "_FortranAEoshiftVector", 4); +} + +TEST_F(RuntimeCallTest, genMatmulTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value matrixA = firBuilder->create(loc, seqTy); + mlir::Value matrixB = firBuilder->create(loc, seqTy); + fir::runtime::genMatmul(*firBuilder, loc, matrixA, matrixB, result); + checkCallOpFromResultBox(result, "_FortranAMatmul", 3); +} + +TEST_F(RuntimeCallTest, genPackTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value array = firBuilder->create(loc, seqTy); + mlir::Value mask = firBuilder->create(loc, seqTy); + mlir::Value vector = firBuilder->create(loc, seqTy); + fir::runtime::genPack(*firBuilder, loc, result, array, mask, vector); + checkCallOpFromResultBox(result, "_FortranAPack", 4); +} + +TEST_F(RuntimeCallTest, genReshapeTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value source = firBuilder->create(loc, seqTy); + mlir::Value shape = firBuilder->create(loc, seqTy); + mlir::Value pad = firBuilder->create(loc, seqTy); + mlir::Value order = firBuilder->create(loc, seqTy); + fir::runtime::genReshape(*firBuilder, loc, result, source, shape, pad, order); + checkCallOpFromResultBox(result, "_FortranAReshape", 5); +} + +TEST_F(RuntimeCallTest, genSpreadTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value source = firBuilder->create(loc, seqTy); + mlir::Value dim = firBuilder->create(loc, seqTy); + mlir::Value ncopies = firBuilder->create(loc, seqTy); + fir::runtime::genSpread(*firBuilder, loc, result, source, dim, ncopies); + checkCallOpFromResultBox(result, "_FortranASpread", 4); +} + +TEST_F(RuntimeCallTest, genTransposeTest) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value source = firBuilder->create(loc, seqTy); + fir::runtime::genTranspose(*firBuilder, loc, result, source); + checkCallOpFromResultBox(result, "_FortranATranspose", 2); +} + +TEST_F(RuntimeCallTest, genUnpack) { + auto loc = firBuilder->getUnknownLoc(); + mlir::Type seqTy = + fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty); + mlir::Value result = firBuilder->create(loc, seqTy); + mlir::Value vector = firBuilder->create(loc, seqTy); + mlir::Value mask = firBuilder->create(loc, seqTy); + mlir::Value field = firBuilder->create(loc, seqTy); + fir::runtime::genUnpack(*firBuilder, loc, result, vector, mask, field); + checkCallOpFromResultBox(result, "_FortranAUnpack", 4); +} diff --git a/flang/unittests/Optimizer/CMakeLists.txt b/flang/unittests/Optimizer/CMakeLists.txt --- a/flang/unittests/Optimizer/CMakeLists.txt +++ b/flang/unittests/Optimizer/CMakeLists.txt @@ -13,6 +13,7 @@ Builder/ComplexTest.cpp Builder/DoLoopHelperTest.cpp Builder/FIRBuilderTest.cpp + Builder/Runtime/TransformationalTest.cpp FIRContextTest.cpp InternalNamesTest.cpp KindMappingTest.cpp