[flang-commits] [flang] 8aa86ac - [flang] Add hlfir.set_length operation

Jean Perier via flang-commits flang-commits at lists.llvm.org
Mon Dec 19 00:51:18 PST 2022


Author: Jean Perier
Date: 2022-12-19T09:50:46+01:00
New Revision: 8aa86ac3c4bfb71abfa85e2ee9b1aea1e20e9582

URL: https://github.com/llvm/llvm-project/commit/8aa86ac3c4bfb71abfa85e2ee9b1aea1e20e9582
DIFF: https://github.com/llvm/llvm-project/commit/8aa86ac3c4bfb71abfa85e2ee9b1aea1e20e9582.diff

LOG: [flang] Add hlfir.set_length operation

This will implement evaluate::SetLength where the length of
a character entity is changed (with trimming and padding).

Differential Revision: https://reviews.llvm.org/D140219

Added: 
    flang/test/HLFIR/set_length-codegen.fir
    flang/test/HLFIR/set_length.fir

Modified: 
    flang/include/flang/Optimizer/HLFIR/HLFIROps.td
    flang/lib/Optimizer/Builder/HLFIRTools.cpp
    flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
    flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index 7df8d3db74961..b5e2a4493dcbf 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -236,6 +236,26 @@ def hlfir_ConcatOp : hlfir_Op<"concat", []> {
   let hasVerifier = 1;
 }
 
+def hlfir_SetLengthOp : hlfir_Op<"set_length", []> {
+  let summary = "change the length of a character entity";
+  let description = [{
+    Change the length of character entity. This trims or pads the
+    character argument according to the new length.
+  }];
+
+  let arguments = (ins AnyScalarCharacterEntity:$string,
+                   AnyIntegerType:$length);
+
+  let results = (outs AnyScalarCharacterExpr);
+
+  let assemblyFormat = [{
+    $string `len` $length
+     attr-dict `:` functional-type(operands, results)
+  }];
+
+  let builders = [OpBuilder<(ins "mlir::Value":$string,"mlir::Value":$len)>];
+}
+
 def hlfir_AssociateOp : hlfir_Op<"associate", [AttrSizedOperandSegments,
     DeclareOpInterfaceMethods<fir_FortranVariableOpInterface>]> {
   let summary = "Create a variable from an expression value";

diff  --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index 6903140c3331a..b090da69135c1 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -431,6 +431,9 @@ void hlfir::genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
     if (auto concat = expr.getDefiningOp<hlfir::ConcatOp>()) {
       result.push_back(concat.getLength());
       return;
+    } else if (auto concat = expr.getDefiningOp<hlfir::SetLengthOp>()) {
+      result.push_back(concat.getLength());
+      return;
     } else if (auto asExpr = expr.getDefiningOp<hlfir::AsExprOp>()) {
       hlfir::genLengthParameters(loc, builder, hlfir::Entity{asExpr.getVar()},
                                  result);

diff  --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 95c4a5306d47c..654414ac8603f 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/DialectImplementation.h"
@@ -400,6 +401,24 @@ void hlfir::ConcatOp::build(mlir::OpBuilder &builder,
   build(builder, result, resultType, strings, len);
 }
 
+//===----------------------------------------------------------------------===//
+// SetLengthOp
+//===----------------------------------------------------------------------===//
+
+void hlfir::SetLengthOp::build(mlir::OpBuilder &builder,
+                               mlir::OperationState &result, mlir::Value string,
+                               mlir::Value len) {
+  fir::CharacterType::LenType resultTypeLen = fir::CharacterType::unknownLen();
+  if (auto cstLen = fir::getIntIfConstant(len))
+    resultTypeLen = *cstLen;
+  unsigned kind = getCharacterKind(string.getType());
+  auto resultType = hlfir::ExprType::get(
+      builder.getContext(), hlfir::ExprType::Shape{},
+      fir::CharacterType::get(builder.getContext(), kind, resultTypeLen),
+      false);
+  build(builder, result, resultType, string, len);
+}
+
 //===----------------------------------------------------------------------===//
 // AssociateOp
 //===----------------------------------------------------------------------===//

diff  --git a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
index 491d75fe4eb1e..90951f8ed32c3 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
@@ -228,6 +228,36 @@ struct ConcatOpConversion : public mlir::OpConversionPattern<hlfir::ConcatOp> {
   }
 };
 
+struct SetLengthOpConversion
+    : public mlir::OpConversionPattern<hlfir::SetLengthOp> {
+  using mlir::OpConversionPattern<hlfir::SetLengthOp>::OpConversionPattern;
+  explicit SetLengthOpConversion(mlir::MLIRContext *ctx)
+      : mlir::OpConversionPattern<hlfir::SetLengthOp>{ctx} {}
+  mlir::LogicalResult
+  matchAndRewrite(hlfir::SetLengthOp setLength, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    mlir::Location loc = setLength->getLoc();
+    auto module = setLength->getParentOfType<mlir::ModuleOp>();
+    fir::FirOpBuilder builder(rewriter, fir::getKindMapping(module));
+    // Create a temp with the new length.
+    hlfir::Entity string{getBufferizedExprStorage(adaptor.getString())};
+    auto charType = hlfir::getFortranElementType(setLength.getType());
+    llvm::StringRef tmpName{".tmp"};
+    llvm::SmallVector<mlir::Value, 1> lenParams{adaptor.getLength()};
+    auto alloca = builder.createTemporary(loc, charType, tmpName,
+                                          /*shape=*/std::nullopt, lenParams);
+    auto declareOp = builder.create<hlfir::DeclareOp>(
+        loc, alloca, tmpName, /*shape=*/mlir::Value{}, lenParams,
+        fir::FortranVariableFlagsAttr{});
+    // Assign string value to the created temp.
+    builder.create<hlfir::AssignOp>(loc, string, declareOp.getBase());
+    mlir::Value bufferizedExpr =
+        packageBufferizedExpr(loc, builder, alloca, false);
+    rewriter.replaceOp(setLength, bufferizedExpr);
+    return mlir::success();
+  }
+};
+
 struct AssociateOpConversion
     : public mlir::OpConversionPattern<hlfir::AssociateOp> {
   using mlir::OpConversionPattern<hlfir::AssociateOp>::OpConversionPattern;
@@ -401,10 +431,11 @@ class BufferizeHLFIR : public hlfir::impl::BufferizeHLFIRBase<BufferizeHLFIR> {
     patterns.insert<ApplyOpConversion, AsExprOpConversion, AssignOpConversion,
                     AssociateOpConversion, ConcatOpConversion,
                     ElementalOpConversion, EndAssociateOpConversion,
-                    NoReassocOpConversion>(context);
+                    NoReassocOpConversion, SetLengthOpConversion>(context);
     mlir::ConversionTarget target(*context);
     target.addIllegalOp<hlfir::ApplyOp, hlfir::AssociateOp, hlfir::ElementalOp,
-                        hlfir::EndAssociateOp, hlfir::YieldElementOp>();
+                        hlfir::EndAssociateOp, hlfir::SetLengthOp,
+                        hlfir::YieldElementOp>();
     target.markUnknownOpDynamicallyLegal([](mlir::Operation *op) {
       return llvm::all_of(
                  op->getResultTypes(),

diff  --git a/flang/test/HLFIR/set_length-codegen.fir b/flang/test/HLFIR/set_length-codegen.fir
new file mode 100644
index 0000000000000..a54cfc00ffe17
--- /dev/null
+++ b/flang/test/HLFIR/set_length-codegen.fir
@@ -0,0 +1,33 @@
+// Test hlfir.set_length operation lowering to operations operating on memory.
+// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s
+
+func.func @test_cst_len(%str : !fir.boxchar<1>) {
+  %c10 = arith.constant 10 : index
+  %0 = hlfir.set_length %str len %c10 : (!fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,10>>
+  return
+}
+// CHECK-LABEL:   func.func @test_cst_len(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.boxchar<1>) {
+// CHECK:  %[[VAL_1:.*]] = fir.alloca !fir.char<1,10> {bindc_name = ".tmp"}
+// CHECK:  %[[VAL_2:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_1]] typeparams %[[VAL_2]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,10>>, index) -> (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>)
+// CHECK:  hlfir.assign %[[VAL_0]] to %[[VAL_3]]#0 : !fir.boxchar<1>, !fir.ref<!fir.char<1,10>>
+// CHECK:  %[[VAL_4:.*]] = arith.constant false
+// CHECK:  %[[VAL_5:.*]] = fir.undefined tuple<!fir.ref<!fir.char<1,10>>, i1>
+// CHECK:  %[[VAL_6:.*]] = fir.insert_value %[[VAL_5]], %[[VAL_4]], [1 : index] : (tuple<!fir.ref<!fir.char<1,10>>, i1>, i1) -> tuple<!fir.ref<!fir.char<1,10>>, i1>
+// CHECK:  %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_1]], [0 : index] : (tuple<!fir.ref<!fir.char<1,10>>, i1>, !fir.ref<!fir.char<1,10>>) -> tuple<!fir.ref<!fir.char<1,10>>, i1>
+
+func.func @test_dyn_len(%str : !fir.ref<!fir.char<1,10>>, %len : index) {
+  %0 = hlfir.set_length %str len %len : (!fir.ref<!fir.char<1,10>>, index) -> !hlfir.expr<!fir.char<1,?>>
+  return
+}
+// CHECK-LABEL:   func.func @test_dyn_len(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.char<1,10>>,
+// CHECK-SAME:    %[[VAL_1:.*]]: index) {
+// CHECK:  %[[VAL_2:.*]] = fir.alloca !fir.char<1,?>(%[[VAL_1]] : index) {bindc_name = ".tmp"}
+// CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]] typeparams %[[VAL_1]] {uniq_name = ".tmp"} : (!fir.ref<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+// CHECK:  hlfir.assign %[[VAL_0]] to %[[VAL_3]]#0 : !fir.ref<!fir.char<1,10>>, !fir.boxchar<1>
+// CHECK:  %[[VAL_4:.*]] = arith.constant false
+// CHECK:  %[[VAL_5:.*]] = fir.undefined tuple<!fir.ref<!fir.char<1,?>>, i1>
+// CHECK:  %[[VAL_6:.*]] = fir.insert_value %[[VAL_5]], %[[VAL_4]], [1 : index] : (tuple<!fir.ref<!fir.char<1,?>>, i1>, i1) -> tuple<!fir.ref<!fir.char<1,?>>, i1>
+// CHECK:  %[[VAL_7:.*]] = fir.insert_value %[[VAL_6]], %[[VAL_2]], [0 : index] : (tuple<!fir.ref<!fir.char<1,?>>, i1>, !fir.ref<!fir.char<1,?>>) -> tuple<!fir.ref<!fir.char<1,?>>, i1>

diff  --git a/flang/test/HLFIR/set_length.fir b/flang/test/HLFIR/set_length.fir
new file mode 100644
index 0000000000000..099a807f25166
--- /dev/null
+++ b/flang/test/HLFIR/set_length.fir
@@ -0,0 +1,30 @@
+// Test hlfir.set_length operation parse, verify (no errors), and unparse.
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @test_cst_len(%str : !fir.boxchar<1>) {
+  %c10 = arith.constant 10 : index
+  %0 = hlfir.set_length %str len %c10 : (!fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,10>>
+  return
+}
+// CHECK-LABEL:   func.func @test_cst_len(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.boxchar<1>) {
+// CHECK:  %[[VAL_1:.*]] = arith.constant 10 : index
+// CHECK:  %[[VAL_2:.*]] = hlfir.set_length %[[VAL_0]] len %[[VAL_1]] : (!fir.boxchar<1>, index) -> !hlfir.expr<!fir.char<1,10>>
+
+func.func @test_dyn_len(%str : !fir.ref<!fir.char<1,10>>, %len : index) {
+  %0 = hlfir.set_length %str len %len : (!fir.ref<!fir.char<1,10>>, index) -> !hlfir.expr<!fir.char<1,?>>
+  return
+}
+// CHECK-LABEL:   func.func @test_dyn_len(
+// CHECK-SAME:    %[[VAL_0:.*]]: !fir.ref<!fir.char<1,10>>,
+// CHECK-SAME:    %[[VAL_1:.*]]: index) {
+// CHECK:  %[[VAL_2:.*]] = hlfir.set_length %[[VAL_0]] len %[[VAL_1]] : (!fir.ref<!fir.char<1,10>>, index) -> !hlfir.expr<!fir.char<1,?>>
+
+func.func @test_from_expr(%str : !hlfir.expr<!fir.char<1,?>>, %len : index) {
+  %0 = hlfir.set_length %str len %len : (!hlfir.expr<!fir.char<1,?>>, index) -> !hlfir.expr<!fir.char<1,?>>
+  return
+}
+// CHECK-LABEL:   func.func @test_from_expr(
+// CHECK-SAME:    %[[VAL_0:.*]]: !hlfir.expr<!fir.char<1,?>>,
+// CHECK-SAME:    %[[VAL_1:.*]]: index) {
+// CHECK:  %[[VAL_2:.*]] = hlfir.set_length %[[VAL_0]] len %[[VAL_1]] : (!hlfir.expr<!fir.char<1,?>>, index) -> !hlfir.expr<!fir.char<1,?>>


        


More information about the flang-commits mailing list