brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · 13da38e Raw
138 lines · cpp
1//===- CharacterConversion.cpp -- convert between character encodings -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "flang/Optimizer/Dialect/FIRDialect.h"10#include "flang/Optimizer/Dialect/FIROps.h"11#include "flang/Optimizer/Dialect/FIRType.h"12#include "flang/Optimizer/Dialect/Support/FIRContext.h"13#include "flang/Optimizer/Dialect/Support/KindMapping.h"14#include "flang/Optimizer/Transforms/Passes.h"15#include "mlir/Dialect/Affine/IR/AffineOps.h"16#include "mlir/Dialect/Func/IR/FuncOps.h"17#include "mlir/IR/Diagnostics.h"18#include "mlir/Pass/Pass.h"19#include "mlir/Transforms/DialectConversion.h"20#include "llvm/Support/Debug.h"21 22namespace fir {23#define GEN_PASS_DEF_CHARACTERCONVERSION24#include "flang/Optimizer/Transforms/Passes.h.inc"25} // namespace fir26 27#define DEBUG_TYPE "flang-character-conversion"28 29namespace {30 31// TODO: Future hook to select some set of runtime calls.32struct CharacterConversionOptions {33  std::string runtimeName;34};35 36class CharacterConvertConversion37    : public mlir::OpRewritePattern<fir::CharConvertOp> {38public:39  using OpRewritePattern::OpRewritePattern;40 41  llvm::LogicalResult42  matchAndRewrite(fir::CharConvertOp conv,43                  mlir::PatternRewriter &rewriter) const override {44    auto kindMap = fir::getKindMapping(conv->getParentOfType<mlir::ModuleOp>());45    auto loc = conv.getLoc();46 47    LLVM_DEBUG(llvm::dbgs()48               << "running character conversion on " << conv << '\n');49 50    // Establish a loop that executes count iterations.51    auto zero = mlir::arith::ConstantIndexOp::create(rewriter, loc, 0);52    auto one = mlir::arith::ConstantIndexOp::create(rewriter, loc, 1);53    auto idxTy = rewriter.getIndexType();54    auto castCnt =55        fir::ConvertOp::create(rewriter, loc, idxTy, conv.getCount());56    auto countm1 = mlir::arith::SubIOp::create(rewriter, loc, castCnt, one);57    auto loop = fir::DoLoopOp::create(rewriter, loc, zero, countm1, one);58    auto insPt = rewriter.saveInsertionPoint();59    rewriter.setInsertionPointToStart(loop.getBody());60 61    // For each code point in the `from` string, convert naively to the `to`62    // string code point. Conversion is done blindly on size only, not value.63    auto getCharBits = [&](mlir::Type t) {64      auto chrTy = mlir::cast<fir::CharacterType>(65          fir::unwrapSequenceType(fir::dyn_cast_ptrEleTy(t)));66      return kindMap.getCharacterBitsize(chrTy.getFKind());67    };68    auto fromBits = getCharBits(conv.getFrom().getType());69    auto toBits = getCharBits(conv.getTo().getType());70    auto pointerType = [&](unsigned bits) {71      return fir::ReferenceType::get(fir::SequenceType::get(72          fir::SequenceType::ShapeRef{fir::SequenceType::getUnknownExtent()},73          rewriter.getIntegerType(bits)));74    };75    auto fromPtrTy = pointerType(fromBits);76    auto toTy = rewriter.getIntegerType(toBits);77    auto toPtrTy = pointerType(toBits);78    auto fromPtr =79        fir::ConvertOp::create(rewriter, loc, fromPtrTy, conv.getFrom());80    auto toPtr = fir::ConvertOp::create(rewriter, loc, toPtrTy, conv.getTo());81    auto getEleTy = [&](unsigned bits) {82      return fir::ReferenceType::get(rewriter.getIntegerType(bits));83    };84    auto fromi =85        fir::CoordinateOp::create(rewriter, loc, getEleTy(fromBits), fromPtr,86                                  mlir::ValueRange{loop.getInductionVar()});87    auto toi =88        fir::CoordinateOp::create(rewriter, loc, getEleTy(toBits), toPtr,89                                  mlir::ValueRange{loop.getInductionVar()});90    auto load = fir::LoadOp::create(rewriter, loc, fromi);91    mlir::Value icast =92        (fromBits >= toBits)93            ? fir::ConvertOp::create(rewriter, loc, toTy, load).getResult()94            : mlir::arith::ExtUIOp::create(rewriter, loc, toTy, load)95                  .getResult();96    rewriter.replaceOpWithNewOp<fir::StoreOp>(conv, icast, toi);97    rewriter.restoreInsertionPoint(insPt);98    return mlir::success();99  }100};101 102/// Rewrite the `fir.char_convert` op into a loop. This pass must be run only on103/// fir::CharConvertOp.104class CharacterConversion105    : public fir::impl::CharacterConversionBase<CharacterConversion> {106public:107  using fir::impl::CharacterConversionBase<108      CharacterConversion>::CharacterConversionBase;109 110  void runOnOperation() override {111    CharacterConversionOptions clOpts{useRuntimeCalls.getValue()};112    if (clOpts.runtimeName.empty()) {113      auto *context = &getContext();114      auto *func = getOperation();115      mlir::RewritePatternSet patterns(context);116      patterns.insert<CharacterConvertConversion>(context);117      mlir::ConversionTarget target(*context);118      target.addLegalDialect<mlir::affine::AffineDialect, fir::FIROpsDialect,119                             mlir::arith::ArithDialect,120                             mlir::func::FuncDialect>();121 122      // apply the patterns123      target.addIllegalOp<fir::CharConvertOp>();124      if (mlir::failed(mlir::applyPartialConversion(func, target,125                                                    std::move(patterns)))) {126        mlir::emitError(mlir::UnknownLoc::get(context),127                        "error in rewriting character convert op");128        signalPassFailure();129      }130      return;131    }132 133    // TODO: some sort of runtime supported conversion?134    signalPassFailure();135  }136};137} // end anonymous namespace138