[flang-commits] [flang] 36f61d1 - [flang] Add hlfir.concat codegen

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Nov 25 00:40:13 PST 2022


Author: Jean Perier
Date: 2022-11-25T09:39:39+01:00
New Revision: 36f61d14fb851b5ca6e8806890a2ee284be964ab

URL: https://github.com/llvm/llvm-project/commit/36f61d14fb851b5ca6e8806890a2ee284be964ab
DIFF: https://github.com/llvm/llvm-project/commit/36f61d14fb851b5ca6e8806890a2ee284be964ab.diff

LOG: [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

Added: 
    flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
    flang/test/HLFIR/concat-bufferization.fir

Modified: 
    flang/include/flang/Optimizer/HLFIR/Passes.h
    flang/include/flang/Optimizer/HLFIR/Passes.td
    flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.h b/flang/include/flang/Optimizer/HLFIR/Passes.h
index 3e3637a782a89..53d2186843462 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.h
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.h
@@ -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"

diff  --git a/flang/include/flang/Optimizer/HLFIR/Passes.td b/flang/include/flang/Optimizer/HLFIR/Passes.td
index bdb4dc447083a..61c849f2b4f02 100644
--- a/flang/include/flang/Optimizer/HLFIR/Passes.td
+++ b/flang/include/flang/Optimizer/HLFIR/Passes.td
@@ -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

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
new file mode 100644
index 0000000000000..4a8380c2bbbd8
--- /dev/null
+++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
@@ -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>();
+}

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
index 587f00f3c471e..983929b82c805 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
+++ b/flang/lib/Optimizer/HLFIR/Transforms/CMakeLists.txt
@@ -1,6 +1,7 @@
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
 
 add_flang_library(HLFIRTransforms
+  BufferizeHLFIR.cpp
   ConvertToFIR.cpp
 
   DEPENDS

diff  --git a/flang/test/HLFIR/concat-bufferization.fir b/flang/test/HLFIR/concat-bufferization.fir
new file mode 100644
index 0000000000000..a68cc3c1ed2ca
--- /dev/null
+++ b/flang/test/HLFIR/concat-bufferization.fir
@@ -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>
+


        


More information about the flang-commits mailing list