[flang] Add hlfir.concat codegen
hlfir.concat codegen happens in the "bufferization" pass: the pass that place hlfir.expr in memory and transform all operations producing or accepting hlfir.expr arguments into operations operating on memory. Since this pass gets rid of the hlfir.expr type, this is a full translation pass. So far hlfir.concat codegen re-uses the current concatenation lowering helper and only supports concatenation of two strings at a time. This matches what lowering to HLFIR without any optimization produces. More optimized versions will be developed later. Differential Revision: https://reviews.llvm.org/D138673
This commit is contained in:
parent
94b9fbabe8
commit
36f61d14fb
@ -22,6 +22,7 @@ namespace hlfir {
|
||||
#include "flang/Optimizer/HLFIR/Passes.h.inc"
|
||||
|
||||
std::unique_ptr<mlir::Pass> createConvertHLFIRtoFIRPass();
|
||||
std::unique_ptr<mlir::Pass> createBufferizeHLFIRPass();
|
||||
|
||||
#define GEN_PASS_REGISTRATION
|
||||
#include "flang/Optimizer/HLFIR/Passes.h.inc"
|
||||
|
@ -15,4 +15,9 @@ def ConvertHLFIRtoFIR : Pass<"convert-hlfir-to-fir", "::mlir::func::FuncOp"> {
|
||||
let constructor = "hlfir::createConvertHLFIRtoFIRPass()";
|
||||
}
|
||||
|
||||
def BufferizeHLFIR : Pass<"bufferize-hlfir", "::mlir::ModuleOp"> {
|
||||
let summary = "Convert HLFIR operations operating on hlfir.expr into operations on memory";
|
||||
let constructor = "hlfir::createBufferizeHLFIRPass()";
|
||||
}
|
||||
|
||||
#endif //FORTRAN_DIALECT_HLFIR_PASSES
|
||||
|
114
flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
Normal file
114
flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
//===- BufferizeHLFIR.cpp - Bufferize HLFIR ------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file defines a pass that bufferize hlfir.expr. It translates operations
|
||||
// producing or consuming hlfir.expr into operations operating on memory.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "flang/Optimizer/Builder/Character.h"
|
||||
#include "flang/Optimizer/Builder/FIRBuilder.h"
|
||||
#include "flang/Optimizer/Builder/HLFIRTools.h"
|
||||
#include "flang/Optimizer/Builder/MutableBox.h"
|
||||
#include "flang/Optimizer/Builder/Runtime/Assign.h"
|
||||
#include "flang/Optimizer/Builder/Todo.h"
|
||||
#include "flang/Optimizer/Dialect/FIRDialect.h"
|
||||
#include "flang/Optimizer/Dialect/FIROps.h"
|
||||
#include "flang/Optimizer/Dialect/FIRType.h"
|
||||
#include "flang/Optimizer/HLFIR/HLFIROps.h"
|
||||
#include "flang/Optimizer/HLFIR/Passes.h"
|
||||
#include "flang/Optimizer/Support/FIRContext.h"
|
||||
#include "mlir/IR/PatternMatch.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassManager.h"
|
||||
#include "mlir/Transforms/DialectConversion.h"
|
||||
|
||||
namespace hlfir {
|
||||
#define GEN_PASS_DEF_BUFFERIZEHLFIR
|
||||
#include "flang/Optimizer/HLFIR/Passes.h.inc"
|
||||
} // namespace hlfir
|
||||
|
||||
namespace {
|
||||
|
||||
struct AssignOpConversion : public mlir::OpConversionPattern<hlfir::AssignOp> {
|
||||
using mlir::OpConversionPattern<hlfir::AssignOp>::OpConversionPattern;
|
||||
explicit AssignOpConversion(mlir::MLIRContext *ctx)
|
||||
: mlir::OpConversionPattern<hlfir::AssignOp>{ctx} {}
|
||||
mlir::LogicalResult
|
||||
matchAndRewrite(hlfir::AssignOp assign, OpAdaptor adaptor,
|
||||
mlir::ConversionPatternRewriter &rewriter) const override {
|
||||
rewriter.replaceOpWithNewOp<hlfir::AssignOp>(
|
||||
assign, adaptor.getOperands()[0], adaptor.getOperands()[1]);
|
||||
return mlir::success();
|
||||
}
|
||||
};
|
||||
|
||||
struct ConcatOpConversion : public mlir::OpConversionPattern<hlfir::ConcatOp> {
|
||||
using mlir::OpConversionPattern<hlfir::ConcatOp>::OpConversionPattern;
|
||||
explicit ConcatOpConversion(mlir::MLIRContext *ctx)
|
||||
: mlir::OpConversionPattern<hlfir::ConcatOp>{ctx} {}
|
||||
mlir::LogicalResult
|
||||
matchAndRewrite(hlfir::ConcatOp concat, OpAdaptor adaptor,
|
||||
mlir::ConversionPatternRewriter &rewriter) const override {
|
||||
mlir::Location loc = concat->getLoc();
|
||||
auto module = concat->getParentOfType<mlir::ModuleOp>();
|
||||
fir::FirOpBuilder builder(rewriter, fir::getKindMapping(module));
|
||||
assert(adaptor.getStrings().size() >= 2 &&
|
||||
"must have at least two strings operands");
|
||||
if (adaptor.getStrings().size() > 2)
|
||||
TODO(loc, "codegen of optimized chained concatenation of more than two "
|
||||
"strings");
|
||||
hlfir::Entity lhs{adaptor.getStrings()[0]};
|
||||
hlfir::Entity rhs{adaptor.getStrings()[1]};
|
||||
auto [lhsExv, c1] = hlfir::translateToExtendedValue(loc, builder, lhs);
|
||||
auto [rhsExv, c2] = hlfir::translateToExtendedValue(loc, builder, rhs);
|
||||
assert(!c1 && !c2 && "expected variables");
|
||||
fir::ExtendedValue res =
|
||||
fir::factory::CharacterExprHelper{builder, loc}.createConcatenate(
|
||||
*lhsExv.getCharBox(), *rhsExv.getCharBox());
|
||||
auto hlfirTempRes = hlfir::genDeclare(loc, builder, res, "tmp",
|
||||
fir::FortranVariableFlagsAttr{});
|
||||
rewriter.replaceOp(concat, hlfirTempRes);
|
||||
return mlir::success();
|
||||
}
|
||||
};
|
||||
|
||||
class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase<BufferizeHLFIR> {
|
||||
public:
|
||||
void runOnOperation() override {
|
||||
// TODO: make this a pass operating on FuncOp. The issue is that
|
||||
// FirOpBuilder helpers may generate new FuncOp because of runtime/llvm
|
||||
// intrinsics calls creation. This may create race conflict if the pass is
|
||||
// scheduleed on FuncOp. A solution could be to provide an optional mutex
|
||||
// when building a FirOpBuilder and locking around FuncOp and GlobalOp
|
||||
// creation, but this needs a bit more thinking, so at this point the pass
|
||||
// is scheduled on the moduleOp.
|
||||
auto module = this->getOperation();
|
||||
auto *context = &getContext();
|
||||
mlir::RewritePatternSet patterns(context);
|
||||
patterns.insert<AssignOpConversion, ConcatOpConversion>(context);
|
||||
mlir::ConversionTarget target(*context);
|
||||
target.markUnknownOpDynamicallyLegal([](mlir::Operation *op) {
|
||||
return llvm::all_of(
|
||||
op->getResultTypes(),
|
||||
[](mlir::Type ty) { return !ty.isa<hlfir::ExprType>(); }) &&
|
||||
llvm::all_of(op->getOperandTypes(), [](mlir::Type ty) {
|
||||
return !ty.isa<hlfir::ExprType>();
|
||||
});
|
||||
});
|
||||
if (mlir::failed(
|
||||
mlir::applyFullConversion(module, target, std::move(patterns)))) {
|
||||
mlir::emitError(mlir::UnknownLoc::get(context),
|
||||
"failure in HLFIR bufferization pass");
|
||||
signalPassFailure();
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<mlir::Pass> hlfir::createBufferizeHLFIRPass() {
|
||||
return std::make_unique<BufferizeHLFIR>();
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
|
||||
|
||||
add_flang_library(HLFIRTransforms
|
||||
BufferizeHLFIR.cpp
|
||||
ConvertToFIR.cpp
|
||||
|
||||
DEPENDS
|
||||
|
127
flang/test/HLFIR/concat-bufferization.fir
Normal file
127
flang/test/HLFIR/concat-bufferization.fir
Normal file
@ -0,0 +1,127 @@
|
||||
// Test hlfir.concat operation lowering to operations operating on memory.
|
||||
|
||||
// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s
|
||||
|
||||
|
||||
func.func @concat(%arg0: !fir.boxchar<1>, %arg1: !fir.boxchar<1>, %arg2: !fir.boxchar<1>) {
|
||||
%0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%1:2 = hlfir.declare %0#0 typeparams %0#1 {uniq_name = "c1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%2:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%3:2 = hlfir.declare %2#0 typeparams %2#1 {uniq_name = "c2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%4:2 = fir.unboxchar %arg2 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%5:2 = hlfir.declare %4#0 typeparams %4#1 {uniq_name = "c3"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%6 = arith.addi %2#1, %4#1 : index
|
||||
%7 = hlfir.concat %3#0, %5#0 len %6 : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
|
||||
hlfir.assign %7 to %1#0 : !hlfir.expr<!fir.char<1,?>>, !fir.boxchar<1>
|
||||
return
|
||||
}
|
||||
// CHECK-LABEL: func.func @concat(
|
||||
// CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.boxchar<1>,
|
||||
// CHECK-SAME: %[[VAL_1:[^:]*]]: !fir.boxchar<1>,
|
||||
// CHECK-SAME: %[[VAL_2:[^:]*]]: !fir.boxchar<1>) {
|
||||
// CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]]#0 typeparams %[[VAL_3]]#1 {uniq_name = "c1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_5:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]]#0 typeparams %[[VAL_5]]#1 {uniq_name = "c2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_7:.*]]:2 = fir.unboxchar %[[VAL_2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_8:.*]]:2 = hlfir.declare %[[VAL_7]]#0 typeparams %[[VAL_7]]#1 {uniq_name = "c3"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_9:.*]] = arith.addi %[[VAL_5]]#1, %[[VAL_7]]#1 : index
|
||||
// CHECK: %[[VAL_10:.*]] = arith.addi %[[VAL_5]]#1, %[[VAL_7]]#1 : index
|
||||
// CHECK: %[[VAL_11:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_10]] : index) {bindc_name = ".chrtmp"}
|
||||
// CHECK: %[[VAL_12:.*]] = arith.constant 1 : i64
|
||||
// CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_5]]#1 : (index) -> i64
|
||||
// CHECK: %[[VAL_14:.*]] = arith.muli %[[VAL_12]], %[[VAL_13]] : i64
|
||||
// CHECK: %[[VAL_15:.*]] = arith.constant false
|
||||
// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: fir.call @llvm.memmove.p0.p0.i64(%[[VAL_16]], %[[VAL_17]], %[[VAL_14]], %[[VAL_15]]) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
|
||||
// CHECK: %[[VAL_18:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[VAL_19:.*]] = arith.subi %[[VAL_10]], %[[VAL_18]] : index
|
||||
// CHECK: fir.do_loop %[[VAL_20:.*]] = %[[VAL_5]]#1 to %[[VAL_19]] step %[[VAL_18]] {
|
||||
// CHECK: %[[VAL_21:.*]] = arith.subi %[[VAL_20]], %[[VAL_5]]#1 : index
|
||||
// CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_8]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_23:.*]] = fir.coordinate_of %[[VAL_22]], %[[VAL_21]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_24:.*]] = fir.load %[[VAL_23]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_26:.*]] = fir.coordinate_of %[[VAL_25]], %[[VAL_20]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: fir.store %[[VAL_24]] to %[[VAL_26]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: }
|
||||
// CHECK: %[[VAL_27:.*]]:2 = hlfir.declare %[[VAL_11]] typeparams %[[VAL_10]] {uniq_name = "tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: hlfir.assign %[[VAL_27]]#0 to %[[VAL_4]]#0 : !fir.boxchar<1>, !fir.boxchar<1>
|
||||
|
||||
|
||||
func.func @concat_chained(%arg0: !fir.boxchar<1>, %arg1: !fir.boxchar<1>, %arg2: !fir.boxchar<1>, %arg3: !fir.boxchar<1>) {
|
||||
%0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%1:2 = hlfir.declare %0#0 typeparams %0#1 {uniq_name = "c1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%2:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%3:2 = hlfir.declare %2#0 typeparams %2#1 {uniq_name = "c2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%4:2 = fir.unboxchar %arg2 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%5:2 = hlfir.declare %4#0 typeparams %4#1 {uniq_name = "c3"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%6:2 = fir.unboxchar %arg3 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
%7:2 = hlfir.declare %6#0 typeparams %6#1 {uniq_name = "c4"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
%8 = arith.addi %2#1, %4#1 : index
|
||||
%9 = hlfir.concat %3#0, %5#0 len %8 : (!fir.boxchar<1>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
|
||||
%10 = arith.addi %8, %6#1 : index
|
||||
%11 = hlfir.concat %9, %7#0 len %10 : (!hlfir.expr<!fir.char<1,?>>, !fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,?>>
|
||||
hlfir.assign %11 to %1#0 : !hlfir.expr<!fir.char<1,?>>, !fir.boxchar<1>
|
||||
return
|
||||
}
|
||||
// CHECK-LABEL: func.func @concat_chained(
|
||||
// CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.boxchar<1>,
|
||||
// CHECK-SAME: %[[VAL_1:[^:]*]]: !fir.boxchar<1>,
|
||||
// CHECK-SAME: %[[VAL_2:[^:]*]]: !fir.boxchar<1>,
|
||||
// CHECK-SAME: %[[VAL_3:[^:]*]]: !fir.boxchar<1>) {
|
||||
// CHECK: %[[VAL_4:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]#0 typeparams %[[VAL_4]]#1 {uniq_name = "c1"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[VAL_1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 {uniq_name = "c2"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_8:.*]]:2 = fir.unboxchar %[[VAL_2]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]]#0 typeparams %[[VAL_8]]#1 {uniq_name = "c3"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_10:.*]]:2 = fir.unboxchar %[[VAL_3]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
|
||||
// CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]]#0 typeparams %[[VAL_10]]#1 {uniq_name = "c4"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_6]]#1, %[[VAL_8]]#1 : index
|
||||
// CHECK: %[[VAL_13:.*]] = arith.addi %[[VAL_6]]#1, %[[VAL_8]]#1 : index
|
||||
// CHECK: %[[VAL_14:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_13]] : index) {bindc_name = ".chrtmp"}
|
||||
// CHECK: %[[VAL_15:.*]] = arith.constant 1 : i64
|
||||
// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_6]]#1 : (index) -> i64
|
||||
// CHECK: %[[VAL_17:.*]] = arith.muli %[[VAL_15]], %[[VAL_16]] : i64
|
||||
// CHECK: %[[VAL_18:.*]] = arith.constant false
|
||||
// CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_14]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_7]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: fir.call @llvm.memmove.p0.p0.i64(%[[VAL_19]], %[[VAL_20]], %[[VAL_17]], %[[VAL_18]]) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
|
||||
// CHECK: %[[VAL_21:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[VAL_22:.*]] = arith.subi %[[VAL_13]], %[[VAL_21]] : index
|
||||
// CHECK: fir.do_loop %[[VAL_23:.*]] = %[[VAL_6]]#1 to %[[VAL_22]] step %[[VAL_21]] {
|
||||
// CHECK: %[[VAL_24:.*]] = arith.subi %[[VAL_23]], %[[VAL_6]]#1 : index
|
||||
// CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_9]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_26:.*]] = fir.coordinate_of %[[VAL_25]], %[[VAL_24]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_27:.*]] = fir.load %[[VAL_26]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_14]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_29:.*]] = fir.coordinate_of %[[VAL_28]], %[[VAL_23]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: fir.store %[[VAL_27]] to %[[VAL_29]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: }
|
||||
// CHECK: %[[VAL_30:.*]]:2 = hlfir.declare %[[VAL_14]] typeparams %[[VAL_13]] {uniq_name = "tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: %[[VAL_31:.*]] = arith.addi %[[VAL_12]], %[[VAL_10]]#1 : index
|
||||
// CHECK: %[[VAL_32:.*]] = arith.addi %[[VAL_13]], %[[VAL_10]]#1 : index
|
||||
// CHECK: %[[VAL_33:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_32]] : index) {bindc_name = ".chrtmp"}
|
||||
// CHECK: %[[VAL_34:.*]] = arith.constant 1 : i64
|
||||
// CHECK: %[[VAL_35:.*]] = fir.convert %[[VAL_13]] : (index) -> i64
|
||||
// CHECK: %[[VAL_36:.*]] = arith.muli %[[VAL_34]], %[[VAL_35]] : i64
|
||||
// CHECK: %[[VAL_37:.*]] = arith.constant false
|
||||
// CHECK: %[[VAL_38:.*]] = fir.convert %[[VAL_33]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: %[[VAL_39:.*]] = fir.convert %[[VAL_30]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8>
|
||||
// CHECK: fir.call @llvm.memmove.p0.p0.i64(%[[VAL_38]], %[[VAL_39]], %[[VAL_36]], %[[VAL_37]]) : (!fir.ref<i8>, !fir.ref<i8>, i64, i1) -> ()
|
||||
// CHECK: %[[VAL_40:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[VAL_41:.*]] = arith.subi %[[VAL_32]], %[[VAL_40]] : index
|
||||
// CHECK: fir.do_loop %[[VAL_42:.*]] = %[[VAL_13]] to %[[VAL_41]] step %[[VAL_40]] {
|
||||
// CHECK: %[[VAL_43:.*]] = arith.subi %[[VAL_42]], %[[VAL_13]] : index
|
||||
// CHECK: %[[VAL_44:.*]] = fir.convert %[[VAL_11]]#1 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_45:.*]] = fir.coordinate_of %[[VAL_44]], %[[VAL_43]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_46:.*]] = fir.load %[[VAL_45]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: %[[VAL_47:.*]] = fir.convert %[[VAL_33]] : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<?x!fir.char<1>>>
|
||||
// CHECK: %[[VAL_48:.*]] = fir.coordinate_of %[[VAL_47]], %[[VAL_42]] : (!fir.ref<!fir.array<?x!fir.char<1>>>, index) -> !fir.ref<!fir.char<1>>
|
||||
// CHECK: fir.store %[[VAL_46]] to %[[VAL_48]] : !fir.ref<!fir.char<1>>
|
||||
// CHECK: }
|
||||
// CHECK: %[[VAL_49:.*]]:2 = hlfir.declare %[[VAL_33]] typeparams %[[VAL_32]] {uniq_name = "tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
|
||||
// CHECK: hlfir.assign %[[VAL_49]]#0 to %[[VAL_5]]#0 : !fir.boxchar<1>, !fir.boxchar<1>
|
||||
|
Loading…
x
Reference in New Issue
Block a user