forked from OSchip/llvm-project
[fir] Add fir character builder
This patch adds the FIR builder to generate the numeric intrinsic runtime call. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: rovka Differential Revision: https://reviews.llvm.org/D114900 Co-authored-by: Jean Perier <jperier@nvidia.com> Co-authored-by: mleair <leairmark@gmail.com>
This commit is contained in:
parent
c32421c925
commit
d59a0f58f4
|
@ -0,0 +1,124 @@
|
|||
//===-- Character.h -- generate calls to character runtime API --*- 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_OPTIMIZER_BUILDER_RUNTIME_CHARACTER_H
|
||||
#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CHARACTER_H
|
||||
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
|
||||
namespace fir {
|
||||
class ExtendedValue;
|
||||
class FirOpBuilder;
|
||||
} // namespace fir
|
||||
|
||||
namespace fir::runtime {
|
||||
|
||||
/// Generate a call to the `ADJUSTL` runtime.
|
||||
/// This calls the simple runtime entry point that then calls into the more
|
||||
/// complex runtime cases handling left or right adjustments.
|
||||
///
|
||||
/// \p resultBox must be an unallocated allocatable used for the temporary
|
||||
/// result. \p StringBox must be a fir.box describing the adjustl string
|
||||
/// argument. Note that the \p genAdjust() helper is called to do the majority
|
||||
/// of the lowering work.
|
||||
void genAdjustL(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox);
|
||||
|
||||
/// Generate a call to the `ADJUSTR` runtime.
|
||||
/// This calls the simple runtime entry point that then calls into the more
|
||||
/// complex runtime cases handling left or right adjustments.
|
||||
///
|
||||
/// \p resultBox must be an unallocated allocatable used for the temporary
|
||||
/// result. \p StringBox must be a fir.box describing the adjustr string
|
||||
/// argument. Note that the \p genAdjust() helper is called to do the majority
|
||||
/// of the lowering work.
|
||||
void genAdjustR(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox);
|
||||
|
||||
/// Generate call to a character comparison for two ssa-values of type
|
||||
/// `boxchar`.
|
||||
mlir::Value genCharCompare(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::arith::CmpIPredicate cmp,
|
||||
const fir::ExtendedValue &lhs,
|
||||
const fir::ExtendedValue &rhs);
|
||||
|
||||
/// Generate call to a character comparison op for two unboxed variables. There
|
||||
/// are 4 arguments, 2 for the lhs and 2 for the rhs. Each CHARACTER must pass a
|
||||
/// reference to its buffer (`ref<char<K>>`) and its LEN type parameter (some
|
||||
/// integral type).
|
||||
mlir::Value genCharCompare(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::arith::CmpIPredicate cmp, mlir::Value lhsBuff,
|
||||
mlir::Value lhsLen, mlir::Value rhsBuff,
|
||||
mlir::Value rhsLen);
|
||||
|
||||
/// Generate call to INDEX runtime.
|
||||
/// This calls the simple runtime entry points based on the KIND of the string.
|
||||
/// No descriptors are used.
|
||||
mlir::Value genIndex(fir::FirOpBuilder &builder, mlir::Location loc, int kind,
|
||||
mlir::Value stringBase, mlir::Value stringLen,
|
||||
mlir::Value substringBase, mlir::Value substringLen,
|
||||
mlir::Value back);
|
||||
|
||||
/// Generate call to INDEX runtime.
|
||||
/// This calls the descriptor based runtime call implementation for the index
|
||||
/// intrinsic.
|
||||
void genIndexDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::Value substringBox, mlir::Value backOpt,
|
||||
mlir::Value kind);
|
||||
|
||||
/// Generate call to repeat runtime.
|
||||
/// \p resultBox must be an unallocated allocatable used for the temporary
|
||||
/// result. \p stringBox must be a fir.box describing repeat string argument.
|
||||
/// \p ncopies must be a value representing the number of copies.
|
||||
/// The runtime will always allocate the resultBox.
|
||||
void genRepeat(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::Value ncopies);
|
||||
|
||||
/// Generate call to trim runtime.
|
||||
/// \p resultBox must be an unallocated allocatable used for the temporary
|
||||
/// result. \p stringBox must be a fir.box describing trim string argument.
|
||||
/// The runtime will always allocate the resultBox.
|
||||
void genTrim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox);
|
||||
|
||||
/// Generate call to scan runtime.
|
||||
/// This calls the descriptor based runtime call implementation of the scan
|
||||
/// intrinsics.
|
||||
void genScanDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::Value setBox, mlir::Value backBox,
|
||||
mlir::Value kind);
|
||||
|
||||
/// Generate call to the scan runtime routine that is specialized on
|
||||
/// \param kind.
|
||||
/// The \param kind represents the kind of the elements in the strings.
|
||||
mlir::Value genScan(fir::FirOpBuilder &builder, mlir::Location loc, int kind,
|
||||
mlir::Value stringBase, mlir::Value stringLen,
|
||||
mlir::Value setBase, mlir::Value setLen, mlir::Value back);
|
||||
|
||||
/// Generate call to verify runtime.
|
||||
/// This calls the descriptor based runtime call implementation of the scan
|
||||
/// intrinsics.
|
||||
void genVerifyDescriptor(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::Value setBox, mlir::Value backBox,
|
||||
mlir::Value kind);
|
||||
|
||||
/// Generate call to the verify runtime routine that is specialized on
|
||||
/// \param kind.
|
||||
/// The \param kind represents the kind of the elements in the strings.
|
||||
mlir::Value genVerify(fir::FirOpBuilder &builder, mlir::Location loc, int kind,
|
||||
mlir::Value stringBase, mlir::Value stringLen,
|
||||
mlir::Value setBase, mlir::Value setLen,
|
||||
mlir::Value back);
|
||||
|
||||
} // namespace fir::runtime
|
||||
|
||||
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_CHARACTER_H
|
|
@ -8,6 +8,7 @@ add_flang_library(FIRBuilder
|
|||
FIRBuilder.cpp
|
||||
MutableBox.cpp
|
||||
Runtime/Assign.cpp
|
||||
Runtime/Character.cpp
|
||||
Runtime/Derived.cpp
|
||||
Runtime/Numeric.cpp
|
||||
Runtime/Reduction.cpp
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
//===-- Character.cpp -- runtime for CHARACTER type entities --------------===//
|
||||
//
|
||||
// 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/Character.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/character.h"
|
||||
#include "mlir/Dialect/StandardOps/IR/Ops.h"
|
||||
|
||||
using namespace Fortran::runtime;
|
||||
|
||||
/// Generate calls to string handling intrinsics such as index, scan, and
|
||||
/// verify. These are the descriptor based implementations that take four
|
||||
/// arguments (string1, string2, back, kind).
|
||||
template <typename FN>
|
||||
static void genCharacterSearch(FN func, fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value string1Box, mlir::Value string2Box,
|
||||
mlir::Value backBox, mlir::Value kind) {
|
||||
|
||||
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,
|
||||
string1Box, string2Box, backBox,
|
||||
kind, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, func, args);
|
||||
}
|
||||
|
||||
/// Helper function to recover the KIND from the FIR type.
|
||||
static int discoverKind(mlir::Type ty) {
|
||||
if (auto charTy = ty.dyn_cast<fir::CharacterType>())
|
||||
return charTy.getFKind();
|
||||
if (auto eleTy = fir::dyn_cast_ptrEleTy(ty))
|
||||
return discoverKind(eleTy);
|
||||
if (auto arrTy = ty.dyn_cast<fir::SequenceType>())
|
||||
return discoverKind(arrTy.getEleTy());
|
||||
if (auto boxTy = ty.dyn_cast<fir::BoxCharType>())
|
||||
return discoverKind(boxTy.getEleTy());
|
||||
if (auto boxTy = ty.dyn_cast<fir::BoxType>())
|
||||
return discoverKind(boxTy.getEleTy());
|
||||
llvm_unreachable("unexpected character type");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Lower character operations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Generate a call to the `ADJUST[L|R]` runtime.
|
||||
///
|
||||
/// \p resultBox must be an unallocated allocatable used for the temporary
|
||||
/// result. \p StringBox must be a fir.box describing the adjustr string
|
||||
/// argument. The \p adjustFunc should be a mlir::FuncOp for the appropriate
|
||||
/// runtime entry function.
|
||||
static void genAdjust(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::FuncOp &adjustFunc) {
|
||||
|
||||
auto fTy = adjustFunc.getType();
|
||||
auto sourceLine =
|
||||
fir::factory::locationToLineNo(builder, loc, fTy.getInput(3));
|
||||
auto sourceFile = fir::factory::locationToFilename(builder, loc);
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, resultBox,
|
||||
stringBox, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, adjustFunc, args);
|
||||
}
|
||||
|
||||
void fir::runtime::genAdjustL(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox) {
|
||||
auto adjustFunc =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(Adjustl)>(loc, builder);
|
||||
genAdjust(builder, loc, resultBox, stringBox, adjustFunc);
|
||||
}
|
||||
|
||||
void fir::runtime::genAdjustR(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox) {
|
||||
auto adjustFunc =
|
||||
fir::runtime::getRuntimeFunc<mkRTKey(Adjustr)>(loc, builder);
|
||||
genAdjust(builder, loc, resultBox, stringBox, adjustFunc);
|
||||
}
|
||||
|
||||
mlir::Value
|
||||
fir::runtime::genCharCompare(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::arith::CmpIPredicate cmp,
|
||||
mlir::Value lhsBuff, mlir::Value lhsLen,
|
||||
mlir::Value rhsBuff, mlir::Value rhsLen) {
|
||||
mlir::FuncOp beginFunc;
|
||||
switch (discoverKind(lhsBuff.getType())) {
|
||||
case 1:
|
||||
beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar1)>(
|
||||
loc, builder);
|
||||
break;
|
||||
case 2:
|
||||
beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar2)>(
|
||||
loc, builder);
|
||||
break;
|
||||
case 4:
|
||||
beginFunc = fir::runtime::getRuntimeFunc<mkRTKey(CharacterCompareScalar4)>(
|
||||
loc, builder);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("runtime does not support CHARACTER KIND");
|
||||
}
|
||||
auto fTy = beginFunc.getType();
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, lhsBuff, rhsBuff,
|
||||
lhsLen, rhsLen);
|
||||
auto tri = builder.create<fir::CallOp>(loc, beginFunc, args).getResult(0);
|
||||
auto zero = builder.createIntegerConstant(loc, tri.getType(), 0);
|
||||
return builder.create<mlir::arith::CmpIOp>(loc, cmp, tri, zero);
|
||||
}
|
||||
|
||||
mlir::Value fir::runtime::genCharCompare(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc,
|
||||
mlir::arith::CmpIPredicate cmp,
|
||||
const fir::ExtendedValue &lhs,
|
||||
const fir::ExtendedValue &rhs) {
|
||||
if (lhs.getBoxOf<fir::BoxValue>() || rhs.getBoxOf<fir::BoxValue>())
|
||||
TODO(loc, "character compare from descriptors");
|
||||
auto allocateIfNotInMemory = [&](mlir::Value base) -> mlir::Value {
|
||||
if (fir::isa_ref_type(base.getType()))
|
||||
return base;
|
||||
auto mem =
|
||||
builder.create<fir::AllocaOp>(loc, base.getType(), /*pinned=*/false);
|
||||
builder.create<fir::StoreOp>(loc, base, mem);
|
||||
return mem;
|
||||
};
|
||||
auto lhsBuffer = allocateIfNotInMemory(fir::getBase(lhs));
|
||||
auto rhsBuffer = allocateIfNotInMemory(fir::getBase(rhs));
|
||||
return genCharCompare(builder, loc, cmp, lhsBuffer, fir::getLen(lhs),
|
||||
rhsBuffer, fir::getLen(rhs));
|
||||
}
|
||||
|
||||
mlir::Value fir::runtime::genIndex(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, int kind,
|
||||
mlir::Value stringBase,
|
||||
mlir::Value stringLen,
|
||||
mlir::Value substringBase,
|
||||
mlir::Value substringLen, mlir::Value back) {
|
||||
mlir::FuncOp indexFunc;
|
||||
switch (kind) {
|
||||
case 1:
|
||||
indexFunc = fir::runtime::getRuntimeFunc<mkRTKey(Index1)>(loc, builder);
|
||||
break;
|
||||
case 2:
|
||||
indexFunc = fir::runtime::getRuntimeFunc<mkRTKey(Index2)>(loc, builder);
|
||||
break;
|
||||
case 4:
|
||||
indexFunc = fir::runtime::getRuntimeFunc<mkRTKey(Index4)>(loc, builder);
|
||||
break;
|
||||
default:
|
||||
fir::emitFatalError(
|
||||
loc, "unsupported CHARACTER kind value. Runtime expects 1, 2, or 4.");
|
||||
}
|
||||
auto fTy = indexFunc.getType();
|
||||
auto args =
|
||||
fir::runtime::createArguments(builder, loc, fTy, stringBase, stringLen,
|
||||
substringBase, substringLen, back);
|
||||
return builder.create<fir::CallOp>(loc, indexFunc, args).getResult(0);
|
||||
}
|
||||
|
||||
void fir::runtime::genIndexDescriptor(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value stringBox,
|
||||
mlir::Value substringBox,
|
||||
mlir::Value backOpt, mlir::Value kind) {
|
||||
auto indexFunc = fir::runtime::getRuntimeFunc<mkRTKey(Index)>(loc, builder);
|
||||
genCharacterSearch(indexFunc, builder, loc, resultBox, stringBox,
|
||||
substringBox, backOpt, kind);
|
||||
}
|
||||
|
||||
void fir::runtime::genRepeat(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox,
|
||||
mlir::Value ncopies) {
|
||||
auto repeatFunc = fir::runtime::getRuntimeFunc<mkRTKey(Repeat)>(loc, builder);
|
||||
auto fTy = repeatFunc.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, stringBox, ncopies, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, repeatFunc, args);
|
||||
}
|
||||
|
||||
void fir::runtime::genTrim(fir::FirOpBuilder &builder, mlir::Location loc,
|
||||
mlir::Value resultBox, mlir::Value stringBox) {
|
||||
auto trimFunc = fir::runtime::getRuntimeFunc<mkRTKey(Trim)>(loc, builder);
|
||||
auto fTy = trimFunc.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,
|
||||
stringBox, sourceFile, sourceLine);
|
||||
builder.create<fir::CallOp>(loc, trimFunc, args);
|
||||
}
|
||||
|
||||
void fir::runtime::genScanDescriptor(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, mlir::Value resultBox,
|
||||
mlir::Value stringBox, mlir::Value setBox,
|
||||
mlir::Value backBox, mlir::Value kind) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Scan)>(loc, builder);
|
||||
genCharacterSearch(func, builder, loc, resultBox, stringBox, setBox, backBox,
|
||||
kind);
|
||||
}
|
||||
|
||||
mlir::Value fir::runtime::genScan(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, int kind,
|
||||
mlir::Value stringBase, mlir::Value stringLen,
|
||||
mlir::Value setBase, mlir::Value setLen,
|
||||
mlir::Value back) {
|
||||
mlir::FuncOp func;
|
||||
switch (kind) {
|
||||
case 1:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Scan1)>(loc, builder);
|
||||
break;
|
||||
case 2:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Scan2)>(loc, builder);
|
||||
break;
|
||||
case 4:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Scan4)>(loc, builder);
|
||||
break;
|
||||
default:
|
||||
fir::emitFatalError(
|
||||
loc, "unsupported CHARACTER kind value. Runtime expects 1, 2, or 4.");
|
||||
}
|
||||
auto fTy = func.getType();
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, stringBase,
|
||||
stringLen, setBase, setLen, back);
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
||||
|
||||
void fir::runtime::genVerifyDescriptor(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc,
|
||||
mlir::Value resultBox,
|
||||
mlir::Value stringBox,
|
||||
mlir::Value setBox, mlir::Value backBox,
|
||||
mlir::Value kind) {
|
||||
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Verify)>(loc, builder);
|
||||
genCharacterSearch(func, builder, loc, resultBox, stringBox, setBox, backBox,
|
||||
kind);
|
||||
}
|
||||
|
||||
mlir::Value fir::runtime::genVerify(fir::FirOpBuilder &builder,
|
||||
mlir::Location loc, int kind,
|
||||
mlir::Value stringBase,
|
||||
mlir::Value stringLen, mlir::Value setBase,
|
||||
mlir::Value setLen, mlir::Value back) {
|
||||
mlir::FuncOp func;
|
||||
switch (kind) {
|
||||
case 1:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Verify1)>(loc, builder);
|
||||
break;
|
||||
case 2:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Verify2)>(loc, builder);
|
||||
break;
|
||||
case 4:
|
||||
func = fir::runtime::getRuntimeFunc<mkRTKey(Verify4)>(loc, builder);
|
||||
break;
|
||||
default:
|
||||
fir::emitFatalError(
|
||||
loc, "unsupported CHARACTER kind value. Runtime expects 1, 2, or 4.");
|
||||
}
|
||||
auto fTy = func.getType();
|
||||
auto args = fir::runtime::createArguments(builder, loc, fTy, stringBase,
|
||||
stringLen, setBase, setLen, back);
|
||||
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
//===- CharacterTest.cpp -- Character runtime builder unit tests ----------===//
|
||||
//
|
||||
// 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/Character.h"
|
||||
#include "RuntimeCallTestBase.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "flang/Optimizer/Builder/Character.h"
|
||||
|
||||
TEST_F(RuntimeCallTest, genAdjustLTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value string = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
fir::runtime::genAdjustL(*firBuilder, loc, result, string);
|
||||
checkCallOpFromResultBox(result, "_FortranAAdjustl", 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genAdjustRTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value result = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value string = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
fir::runtime::genAdjustR(*firBuilder, loc, result, string);
|
||||
checkCallOpFromResultBox(result, "_FortranAAdjustr", 2);
|
||||
}
|
||||
|
||||
void checkCharCompare1(
|
||||
fir::FirOpBuilder &builder, mlir::Type type, llvm::StringRef fctName) {
|
||||
auto loc = builder.getUnknownLoc();
|
||||
mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
|
||||
mlir::Value lhsBuff = builder.create<fir::UndefOp>(loc, type);
|
||||
mlir::Value lhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value rhsBuff = builder.create<fir::UndefOp>(loc, type);
|
||||
mlir::Value rhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value res = fir::runtime::genCharCompare(builder, loc,
|
||||
mlir::arith::CmpIPredicate::eq, lhsBuff, lhsLen, rhsBuff, rhsLen);
|
||||
checkCallOpFromResultBox(lhsBuff, fctName, 4, /*addLocArgs=*/false);
|
||||
EXPECT_TRUE(mlir::isa<mlir::arith::CmpIOp>(res.getDefiningOp()));
|
||||
}
|
||||
|
||||
void checkCharCompare1AllTypeForKind(
|
||||
fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
|
||||
mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
|
||||
mlir::Type seqCharTy = fir::SequenceType::get(charTy, 10);
|
||||
mlir::Type refCharTy = fir::ReferenceType::get(charTy);
|
||||
mlir::Type boxCharTy = fir::BoxCharType::get(builder.getContext(), kind);
|
||||
mlir::Type boxTy = fir::BoxType::get(charTy);
|
||||
checkCharCompare1(builder, charTy, fctName);
|
||||
checkCharCompare1(builder, seqCharTy, fctName);
|
||||
checkCharCompare1(builder, refCharTy, fctName);
|
||||
checkCharCompare1(builder, boxCharTy, fctName);
|
||||
checkCharCompare1(builder, boxTy, fctName);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genCharCompar1Test) {
|
||||
checkCharCompare1AllTypeForKind(
|
||||
*firBuilder, "_FortranACharacterCompareScalar1", 1);
|
||||
checkCharCompare1AllTypeForKind(
|
||||
*firBuilder, "_FortranACharacterCompareScalar2", 2);
|
||||
checkCharCompare1AllTypeForKind(
|
||||
*firBuilder, "_FortranACharacterCompareScalar4", 4);
|
||||
}
|
||||
|
||||
void checkCharCompare2(
|
||||
fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
|
||||
auto loc = builder.getUnknownLoc();
|
||||
fir::factory::CharacterExprHelper charHelper(builder, loc);
|
||||
mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
|
||||
mlir::Type boxCharTy = fir::BoxCharType::get(builder.getContext(), kind);
|
||||
mlir::Value lhsBuff = builder.create<fir::UndefOp>(loc, boxCharTy);
|
||||
mlir::Value lhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value rhsBuff = builder.create<fir::UndefOp>(loc, boxCharTy);
|
||||
mlir::Value rhsLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
fir::ExtendedValue lhs = charHelper.toExtendedValue(lhsBuff, lhsLen);
|
||||
fir::ExtendedValue rhs = charHelper.toExtendedValue(rhsBuff, rhsLen);
|
||||
mlir::Value res = fir::runtime::genCharCompare(
|
||||
builder, loc, mlir::arith::CmpIPredicate::eq, lhs, rhs);
|
||||
EXPECT_TRUE(mlir::isa<mlir::arith::CmpIOp>(res.getDefiningOp()));
|
||||
auto cmpOp = mlir::dyn_cast<mlir::arith::CmpIOp>(res.getDefiningOp());
|
||||
checkCallOp(cmpOp.lhs().getDefiningOp(), fctName, 4, /*addLocArgs=*/false);
|
||||
auto allocas = res.getParentBlock()->getOps<fir::AllocaOp>();
|
||||
EXPECT_TRUE(llvm::empty(allocas));
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genCharCompare2Test) {
|
||||
checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar1", 1);
|
||||
checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar2", 2);
|
||||
checkCharCompare2(*firBuilder, "_FortranACharacterCompareScalar4", 4);
|
||||
}
|
||||
|
||||
void checkGenIndex(
|
||||
fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
|
||||
auto loc = builder.getUnknownLoc();
|
||||
mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
|
||||
mlir::Value stringBase = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value substringBase = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value substringLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value res = fir::runtime::genIndex(builder, loc, kind, stringBase,
|
||||
stringLen, substringBase, substringLen, back);
|
||||
checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genIndexTest) {
|
||||
checkGenIndex(*firBuilder, "_FortranAIndex1", 1);
|
||||
checkGenIndex(*firBuilder, "_FortranAIndex2", 2);
|
||||
checkGenIndex(*firBuilder, "_FortranAIndex4", 4);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genIndexDescriptorTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value substringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value backOpt = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
|
||||
fir::runtime::genIndexDescriptor(
|
||||
*firBuilder, loc, resultBox, stringBox, substringBox, backOpt, kind);
|
||||
checkCallOpFromResultBox(resultBox, "_FortranAIndex", 5);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genRepeatTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value ncopies = firBuilder->create<fir::UndefOp>(loc, i32Ty);
|
||||
fir::runtime::genRepeat(*firBuilder, loc, resultBox, stringBox, ncopies);
|
||||
checkCallOpFromResultBox(resultBox, "_FortranARepeat", 3);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genTrimTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
fir::runtime::genTrim(*firBuilder, loc, resultBox, stringBox);
|
||||
checkCallOpFromResultBox(resultBox, "_FortranATrim", 2);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genScanDescriptorTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value setBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value backBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
|
||||
fir::runtime::genScanDescriptor(
|
||||
*firBuilder, loc, resultBox, stringBox, setBox, backBox, kind);
|
||||
checkCallOpFromResultBox(resultBox, "_FortranAScan", 5);
|
||||
}
|
||||
|
||||
void checkGenScan(
|
||||
fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
|
||||
auto loc = builder.getUnknownLoc();
|
||||
mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
|
||||
mlir::Type boxTy = fir::BoxType::get(charTy);
|
||||
mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
|
||||
mlir::Value stringBase = builder.create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value setBase = builder.create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value setLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value res = fir::runtime::genScan(
|
||||
builder, loc, kind, stringBase, stringLen, setBase, setLen, back);
|
||||
checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genScanTest) {
|
||||
checkGenScan(*firBuilder, "_FortranAScan1", 1);
|
||||
checkGenScan(*firBuilder, "_FortranAScan2", 2);
|
||||
checkGenScan(*firBuilder, "_FortranAScan4", 4);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genVerifyDescriptorTest) {
|
||||
auto loc = firBuilder->getUnknownLoc();
|
||||
mlir::Value resultBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value setBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value backBox = firBuilder->create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value kind = firBuilder->create<fir::UndefOp>(loc, i32Ty);
|
||||
fir::runtime::genVerifyDescriptor(
|
||||
*firBuilder, loc, resultBox, stringBox, setBox, backBox, kind);
|
||||
checkCallOpFromResultBox(resultBox, "_FortranAVerify", 5);
|
||||
}
|
||||
|
||||
void checkGenVerify(
|
||||
fir::FirOpBuilder &builder, llvm::StringRef fctName, unsigned kind) {
|
||||
auto loc = builder.getUnknownLoc();
|
||||
mlir::Type charTy = fir::CharacterType::get(builder.getContext(), kind, 10);
|
||||
mlir::Type boxTy = fir::BoxType::get(charTy);
|
||||
mlir::Type i32Ty = IntegerType::get(builder.getContext(), 32);
|
||||
mlir::Value stringBase = builder.create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value stringLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value setBase = builder.create<fir::UndefOp>(loc, boxTy);
|
||||
mlir::Value setLen = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value back = builder.create<fir::UndefOp>(loc, i32Ty);
|
||||
mlir::Value res = fir::runtime::genVerify(
|
||||
builder, loc, kind, stringBase, stringLen, setBase, setLen, back);
|
||||
checkCallOp(res.getDefiningOp(), fctName, 5, /*addLocArgs=*/false);
|
||||
}
|
||||
|
||||
TEST_F(RuntimeCallTest, genVerifyTest) {
|
||||
checkGenVerify(*firBuilder, "_FortranAVerify1", 1);
|
||||
checkGenVerify(*firBuilder, "_FortranAVerify2", 2);
|
||||
checkGenVerify(*firBuilder, "_FortranAVerify4", 4);
|
||||
}
|
|
@ -50,6 +50,7 @@ public:
|
|||
c16Ty = fir::ComplexType::get(firBuilder->getContext(), 16);
|
||||
|
||||
seqTy10 = fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
|
||||
boxTy = fir::BoxType::get(mlir::NoneType::get(firBuilder->getContext()));
|
||||
}
|
||||
|
||||
mlir::MLIRContext context;
|
||||
|
@ -71,6 +72,7 @@ public:
|
|||
mlir::Type c10Ty;
|
||||
mlir::Type c16Ty;
|
||||
mlir::Type seqTy10;
|
||||
mlir::Type boxTy;
|
||||
};
|
||||
|
||||
/// Check that the \p op is a `fir::CallOp` operation and its name matches
|
||||
|
|
|
@ -14,6 +14,7 @@ add_flang_unittest(FlangOptimizerTests
|
|||
Builder/DoLoopHelperTest.cpp
|
||||
Builder/FIRBuilderTest.cpp
|
||||
Builder/Runtime/AssignTest.cpp
|
||||
Builder/Runtime/CharacterTest.cpp
|
||||
Builder/Runtime/DerivedTest.cpp
|
||||
Builder/Runtime/NumericTest.cpp
|
||||
Builder/Runtime/ReductionTest.cpp
|
||||
|
|
Loading…
Reference in New Issue