-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[flang] Add hlfir.char_trim operation #156064
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Fortran character trim is currently lowered directly into a runtime call, which makes it more complex to simplify expressions using it. With this patch trim is first lowered into an hlfir.char_trim operation, that is only later transformed into a runtime call. This makes it easier to remove unnecessary calls to trim, as proposed in llvm#154593.
@llvm/pr-subscribers-flang-fir-hlfir Author: Leandro Lupori (luporl) ChangesFortran character trim is currently lowered directly into a runtime With this patch trim is first lowered into an hlfir.char_trim Patch is 26.11 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156064.diff 7 Files Affected:
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index f58dde589aaf5..4b990a1c94c72 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -368,6 +368,23 @@ def hlfir_CmpCharOp : hlfir_Op<"cmpchar",
let hasVerifier = 1;
}
+def hlfir_CharTrimOp
+ : hlfir_Op<
+ "char_trim", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
+ let summary = "trim character";
+ let description = [{ Trim a character string. }];
+
+ let arguments = (ins AnyScalarCharacterEntity:$chr);
+
+ let results = (outs AnyScalarCharacterExpr);
+
+ let assemblyFormat = [{
+ $chr attr-dict `:` functional-type(operands, results)
+ }];
+
+ let builders = [OpBuilder<(ins "mlir::Value":$chr)>];
+}
+
def hlfir_AllOp : hlfir_Op<"all", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
let summary = "ALL transformational intrinsic";
let description = [{
diff --git a/flang/lib/Lower/HlfirIntrinsics.cpp b/flang/lib/Lower/HlfirIntrinsics.cpp
index 39595d6f519ad..b9731e993db8f 100644
--- a/flang/lib/Lower/HlfirIntrinsics.cpp
+++ b/flang/lib/Lower/HlfirIntrinsics.cpp
@@ -159,6 +159,18 @@ class HlfirCharExtremumLowering : public HlfirTransformationalIntrinsic {
hlfir::CharExtremumPredicate pred;
};
+class HlfirCharTrimLowering : public HlfirTransformationalIntrinsic {
+public:
+ HlfirCharTrimLowering(fir::FirOpBuilder &builder, mlir::Location loc)
+ : HlfirTransformationalIntrinsic(builder, loc) {}
+
+protected:
+ mlir::Value
+ lowerImpl(const Fortran::lower::PreparedActualArguments &loweredActuals,
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
+ mlir::Type stmtResultType) override;
+};
+
class HlfirCShiftLowering : public HlfirTransformationalIntrinsic {
public:
using HlfirTransformationalIntrinsic::HlfirTransformationalIntrinsic;
@@ -421,6 +433,15 @@ mlir::Value HlfirCharExtremumLowering::lowerImpl(
return createOp<hlfir::CharExtremumOp>(pred, mlir::ValueRange{operands});
}
+mlir::Value HlfirCharTrimLowering::lowerImpl(
+ const Fortran::lower::PreparedActualArguments &loweredActuals,
+ const fir::IntrinsicArgumentLoweringRules *argLowering,
+ mlir::Type stmtResultType) {
+ auto operands = getOperandVector(loweredActuals, argLowering);
+ assert(operands.size() == 1);
+ return createOp<hlfir::CharTrimOp>(operands[0]);
+}
+
mlir::Value HlfirCShiftLowering::lowerImpl(
const Fortran::lower::PreparedActualArguments &loweredActuals,
const fir::IntrinsicArgumentLoweringRules *argLowering,
@@ -555,6 +576,9 @@ std::optional<hlfir::EntityWithAttributes> Fortran::lower::lowerHlfirIntrinsic(
return HlfirCharExtremumLowering{builder, loc,
hlfir::CharExtremumPredicate::max}
.lower(loweredActuals, argLowering, stmtResultType);
+ if (name == "trim")
+ return HlfirCharTrimLowering{builder, loc}.lower(
+ loweredActuals, argLowering, stmtResultType);
}
return std::nullopt;
}
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 964d183631186..6a2a28e3b6832 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -854,6 +854,32 @@ void hlfir::CmpCharOp::getEffects(
getIntrinsicEffects(getOperation(), effects);
}
+//===----------------------------------------------------------------------===//
+// CharTrimOp
+//===----------------------------------------------------------------------===//
+
+void hlfir::CharTrimOp::build(mlir::OpBuilder &builder,
+ mlir::OperationState &result, mlir::Value chr) {
+ fir::CharacterType::LenType len;
+ if (auto cstLen = getCharacterLengthIfStatic(chr.getType()))
+ len = *cstLen;
+ else
+ len = fir::CharacterType::unknownLen();
+ unsigned kind = getCharacterKind(chr.getType());
+ auto resultType = hlfir::ExprType::get(
+ builder.getContext(), hlfir::ExprType::Shape{},
+ fir::CharacterType::get(builder.getContext(), kind, len),
+ /*polymorphic=*/false);
+ build(builder, result, resultType, chr);
+}
+
+void hlfir::CharTrimOp::getEffects(
+ llvm::SmallVectorImpl<
+ mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
+ &effects) {
+ getIntrinsicEffects(getOperation(), effects);
+}
+
//===----------------------------------------------------------------------===//
// NumericalReductionOp
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
index 8b6c7decb2a0a..a913cfadcefc2 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp
@@ -585,6 +585,34 @@ class CmpCharOpConversion : public HlfirIntrinsicConversion<hlfir::CmpCharOp> {
}
};
+class CharTrimOpConversion
+ : public HlfirIntrinsicConversion<hlfir::CharTrimOp> {
+ using HlfirIntrinsicConversion<hlfir::CharTrimOp>::HlfirIntrinsicConversion;
+
+ llvm::LogicalResult
+ matchAndRewrite(hlfir::CharTrimOp trim,
+ mlir::PatternRewriter &rewriter) const override {
+ fir::FirOpBuilder builder{rewriter, trim.getOperation()};
+ const mlir::Location &loc = trim->getLoc();
+
+ llvm::SmallVector<IntrinsicArgument, 1> inArgs;
+ mlir::Value chr = trim.getChr();
+ inArgs.push_back({chr, chr.getType()});
+
+ auto *argLowering = fir::getIntrinsicArgumentLowering("trim");
+ llvm::SmallVector<fir::ExtendedValue, 1> args =
+ lowerArguments(trim, inArgs, rewriter, argLowering);
+
+ mlir::Type resultType = hlfir::getFortranElementType(trim.getType());
+
+ auto [resultExv, mustBeFreed] =
+ fir::genIntrinsicCall(builder, loc, "trim", resultType, args);
+
+ processReturnValue(trim, resultExv, mustBeFreed, builder, rewriter);
+ return mlir::success();
+ }
+};
+
class LowerHLFIRIntrinsics
: public hlfir::impl::LowerHLFIRIntrinsicsBase<LowerHLFIRIntrinsics> {
public:
@@ -592,14 +620,14 @@ class LowerHLFIRIntrinsics
mlir::ModuleOp module = this->getOperation();
mlir::MLIRContext *context = &getContext();
mlir::RewritePatternSet patterns(context);
- patterns.insert<MatmulOpConversion, MatmulTransposeOpConversion,
- AllOpConversion, AnyOpConversion, SumOpConversion,
- ProductOpConversion, TransposeOpConversion,
- CountOpConversion, DotProductOpConversion,
- MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion,
- MaxlocOpConversion, ArrayShiftOpConversion<hlfir::CShiftOp>,
- ArrayShiftOpConversion<hlfir::EOShiftOp>,
- ReshapeOpConversion, CmpCharOpConversion>(context);
+ patterns.insert<
+ MatmulOpConversion, MatmulTransposeOpConversion, AllOpConversion,
+ AnyOpConversion, SumOpConversion, ProductOpConversion,
+ TransposeOpConversion, CountOpConversion, DotProductOpConversion,
+ MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion,
+ MaxlocOpConversion, ArrayShiftOpConversion<hlfir::CShiftOp>,
+ ArrayShiftOpConversion<hlfir::EOShiftOp>, ReshapeOpConversion,
+ CmpCharOpConversion, CharTrimOpConversion>(context);
// While conceptually this pass is performing dialect conversion, we use
// pattern rewrites here instead of dialect conversion because this pass
diff --git a/flang/test/HLFIR/trim.fir b/flang/test/HLFIR/trim.fir
new file mode 100644
index 0000000000000..8cf4a6d1201bd
--- /dev/null
+++ b/flang/test/HLFIR/trim.fir
@@ -0,0 +1,42 @@
+// RUN: fir-opt --lower-hlfir-intrinsics %s | FileCheck %s
+
+// CHECK-LABEL: func.func @_QPtrim_test(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) {
+// CHECK: %[[VAL_0:.*]] = arith.constant true
+// CHECK: %[[VAL_2:.*]] = arith.constant 0 : index
+// CHECK: %[[VAL_3:.*]] = arith.constant 8 : index
+// CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
+// CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 dummy_scope %[[VAL_5]] {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+// CHECK: %[[VAL_8:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"}
+// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_3]] {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>)
+// CHECK: %[[VAL_10:.*]] = fir.embox %[[VAL_7]]#1 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>>
+// CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.char<1,?>>
+// CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]] typeparams %[[VAL_2]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>>
+// CHECK: fir.store %[[VAL_12]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
+// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>>
+// CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none>
+// CHECK: fir.call @_FortranATrim(%[[VAL_14]], %[[VAL_15]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
+// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
+// CHECK: %[[VAL_18:.*]] = fir.box_elesize %[[VAL_17]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index
+// CHECK: %[[VAL_19:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
+// CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_18]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>)
+// CHECK: %[[VAL_21:.*]] = hlfir.as_expr %[[VAL_20]]#0 move %[[VAL_0]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>>
+// CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_9]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>>
+// CHECK: hlfir.destroy %[[VAL_21]] : !hlfir.expr<!fir.char<1,?>>
+// CHECK: return
+// CHECK: }
+
+func.func @_QPtrim_test(%arg0: !fir.boxchar<1> {fir.bindc_name = "c"}) {
+ %0 = fir.dummy_scope : !fir.dscope
+ %1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+ %2:2 = hlfir.declare %1#0 typeparams %1#1 dummy_scope %0 {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+ %c8 = arith.constant 8 : index
+ %3 = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"}
+ %4:2 = hlfir.declare %3 typeparams %c8 {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>)
+ %5 = hlfir.char_trim %2#0 : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>>
+ hlfir.assign %5 to %4#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>>
+ hlfir.destroy %5 : !hlfir.expr<!fir.char<1,?>>
+ return
+}
diff --git a/flang/test/Lower/HLFIR/trim.f90 b/flang/test/Lower/HLFIR/trim.f90
new file mode 100644
index 0000000000000..ea1bd4fadead2
--- /dev/null
+++ b/flang/test/Lower/HLFIR/trim.f90
@@ -0,0 +1,22 @@
+! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s
+
+! CHECK-LABEL: func.func @_QPtrim_test(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) {
+! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK-NEXT: %[[VAL_2:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK-NEXT: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+! CHECK-NEXT: %[[VAL_4:.*]] = arith.constant 8 : index
+! CHECK-NEXT: %[[VAL_5:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"}
+! CHECK-NEXT: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_4]] {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>)
+! CHECK-NEXT: %[[VAL_7:.*]] = hlfir.char_trim %[[VAL_3]]#0 : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>>
+! CHECK-NEXT: hlfir.assign %[[VAL_7]] to %[[VAL_6]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>>
+! CHECK-NEXT: hlfir.destroy %[[VAL_7]] : !hlfir.expr<!fir.char<1,?>>
+! CHECK-NEXT: return
+! CHECK-NEXT: }
+subroutine trim_test(c)
+ character(*) :: c
+ character(8) :: tc
+
+ tc = trim(c)
+end subroutine
+
diff --git a/flang/test/Lower/volatile-string.f90 b/flang/test/Lower/volatile-string.f90
index f263db7abb5fc..8f392dfab8287 100644
--- a/flang/test/Lower/volatile-string.f90
+++ b/flang/test/Lower/volatile-string.f90
@@ -22,67 +22,56 @@ subroutine assign_different_length(string)
end program
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} {
-! CHECK: %[[VAL_0:.*]] = arith.constant 11 : i32
-! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index
-! CHECK: %[[VAL_2:.*]] = arith.constant true
-! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32
-! CHECK: %[[VAL_4:.*]] = arith.constant 3 : i32
-! CHECK: %[[VAL_5:.*]] = arith.constant false
-! CHECK: %[[VAL_6:.*]] = arith.constant 1 : index
-! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index
-! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>>
-! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,3>>>
-! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"}
-! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
-! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.char<1,3> {bindc_name = "nonvolatile_string", uniq_name = "_QFEnonvolatile_string"}
-! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] typeparams %[[VAL_7]] {uniq_name = "_QFEnonvolatile_string"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>)
-! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFEstring) : !fir.ref<!fir.char<1,3>>
-! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile>
-! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>)
-! CHECK: %[[VAL_17:.*]] = fir.volatile_cast %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.ref<!fir.char<1,3>>
-! CHECK: %[[VAL_18:.*]] = fir.emboxchar %[[VAL_17]], %[[VAL_7]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1>
-! CHECK: fir.call @_QFPassign_same_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
-! CHECK: fir.call @_QFPassign_different_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> ()
-! CHECK: %[[VAL_19:.*]] = fir.address_of(@_QQclX6F) : !fir.ref<!fir.char<1>>
-! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX6F"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>)
-! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_17]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<i8>
-! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_7]] : (index) -> i64
-! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_20]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.ref<i8>
-! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_6]] : (index) -> i64
-! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAIndex1(%[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_5]]) fastmath<contract> : (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i1) -> i64
-! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i64) -> i32
-! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_11]]#0 : i32, !fir.ref<i32>
-! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_11]]#0 : i32, !fir.ref<i32>
-! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>, volatile>
-! CHECK: %[[VAL_28:.*]] = fir.zero_bits !fir.heap<!fir.char<1,3>>
-! CHECK: %[[VAL_29:.*]] = fir.embox %[[VAL_28]] : (!fir.heap<!fir.char<1,3>>) -> !fir.box<!fir.heap<!fir.char<1,3>>>
-! CHECK: fir.store %[[VAL_29]] to %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>
-! CHECK: %[[VAL_30:.*]] = fir.address_of(
-! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: %[[VAL_32:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.box<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>>
-! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (!fir.box<!fir.char<1,3>>) -> !fir.box<none>
-! CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_30]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
-! CHECK: fir.call @_FortranAAdjustl(%[[VAL_31]], %[[VAL_33]], %[[VAL_34]], %[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>
-! CHECK: %[[VAL_36:.*]] = fir.box_elesize %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> index
-! CHECK: %[[VAL_37:.*]] = fir.box_addr %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> !fir.heap<!fir.char<1,3>>
-! CHECK: %[[VAL_38:.*]]:2 = hlfir.declare %[[VAL_37]] typeparams %[[VAL_36]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,3>>, index) -> (!fir.heap<!fir.char<1,3>>, !fir.heap<!fir.char<1,3>>)
-! CHECK: %[[VAL_39:.*]] = hlfir.as_expr %[[VAL_38]]#0 move %[[VAL_2]] : (!fir.heap<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>>
-! CHECK: hlfir.assign %[[VAL_39]] to %[[VAL_16]]#0 : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile>
-! CHECK: hlfir.destroy %[[VAL_39]] : !hlfir.expr<!fir.char<1,3>>
-! CHECK: %[[VAL_40:.*]] = fir.zero_bits !fir.heap<!fir.char<1,?>>
-! CHECK: %[[VAL_41:.*]] = fir.embox %[[VAL_40]] typeparams %[[VAL_1]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>>
-! CHECK: fir.store %[[VAL_41]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
-! CHECK: %[[VAL_42:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>>
-! CHECK: fir.call @_FortranATrim(%[[VAL_42]], %[[VAL_33]], %[[VAL_34]], %[[VAL_0]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> ()
-! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>
-! CHECK: %[[VAL_44:.*]] = fir.box_elesize %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index
-! CHECK: %[[VAL_45:.*]] = fir.box_addr %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>>
-! CHECK: %[[VAL_46:.*]]:2 = hlfir.declare %[[VAL_45]] typeparams %[[VAL_44]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>)
-! CHECK: ...
[truncated]
|
Several tests from gfortran testsuite fail with this change. |
Thank you for the changes @luporl! It looks good to me, and I am not sure why gfortran tests might be failing. |
The runtime Trim function allocates the result, that may have a different length than its input character string.
Thanks for the review @vzakhari! The issue was related to the return type of The last commit fixes all gfortran testsuite failures. |
It makes a lot of sense :) Looks good to me, but please let others comment as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for the fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Fortran character trim is currently lowered directly into a runtime
call, which makes it more complex to simplify expressions using it.
With this patch trim is first lowered into an hlfir.char_trim
operation, that is only later transformed into a runtime call.
This makes it easier to remove unnecessary calls to trim, as
proposed in #154593.