[flang-commits] [flang] [flang] Lower hlfir.cmpchar into inline implementation in simplify-hlfir-intrinsics (PR #155461)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 26 11:02:35 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Valery Dmitriev (valerydmit)
<details>
<summary>Changes</summary>
---
Patch is 64.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/155461.diff
5 Files Affected:
- (modified) flang/include/flang/Optimizer/HLFIR/HLFIROps.td (+20)
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+34)
- (modified) flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp (+208-1)
- (modified) flang/test/HLFIR/invalid.fir (+11)
- (added) flang/test/HLFIR/simplify-hlfir-intrinsics-cmpchar-scalar.fir (+610)
``````````diff
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index db3fb0b90464d..f58dde589aaf5 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -348,6 +348,26 @@ def hlfir_ConcatOp : hlfir_Op<"concat",
let hasVerifier = 1;
}
+def hlfir_CmpCharOp : hlfir_Op<"cmpchar",
+ [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
+ let summary = "compare two characters";
+ let description = [{
+ Compare two character strings of a same character kind.
+ }];
+
+ let arguments = (ins Arith_CmpIPredicateAttr:$predicate,
+ AnyScalarCharacterEntity:$lchr,
+ AnyScalarCharacterEntity:$rchr);
+
+ let results = (outs I1);
+
+ let assemblyFormat = [{
+ $predicate $lchr $rchr attr-dict `:` functional-type(operands, results)
+ }];
+
+ let hasVerifier = 1;
+}
+
def hlfir_AllOp : hlfir_Op<"all", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> {
let summary = "ALL transformational intrinsic";
let description = [{
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 3c5095da0145a..964d183631186 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -820,6 +820,40 @@ void hlfir::ConcatOp::getEffects(
getIntrinsicEffects(getOperation(), effects);
}
+//===----------------------------------------------------------------------===//
+// CmpCharOp
+//===----------------------------------------------------------------------===//
+
+llvm::LogicalResult hlfir::CmpCharOp::verify() {
+ mlir::Value lchr = getLchr();
+ mlir::Value rchr = getRchr();
+
+ unsigned kind = getCharacterKind(lchr.getType());
+ if (kind != getCharacterKind(rchr.getType()))
+ return emitOpError("character arguments must have the same KIND");
+
+ switch (getPredicate()) {
+ case mlir::arith::CmpIPredicate::slt:
+ case mlir::arith::CmpIPredicate::sle:
+ case mlir::arith::CmpIPredicate::eq:
+ case mlir::arith::CmpIPredicate::ne:
+ case mlir::arith::CmpIPredicate::sgt:
+ case mlir::arith::CmpIPredicate::sge:
+ break;
+ default:
+ return emitOpError("expected signed predicate");
+ }
+
+ return mlir::success();
+}
+
+void hlfir::CmpCharOp::getEffects(
+ llvm::SmallVectorImpl<
+ mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
+ &effects) {
+ getIntrinsicEffects(getOperation(), effects);
+}
+
//===----------------------------------------------------------------------===//
// NumericalReductionOp
//===----------------------------------------------------------------------===//
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
index fe12f49c655b8..e7f6105d1ac4f 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/SimplifyHLFIRIntrinsics.cpp
@@ -2078,6 +2078,213 @@ class ArrayShiftConversion : public mlir::OpRewritePattern<Op> {
}
};
+class CmpCharOpConversion : public mlir::OpRewritePattern<hlfir::CmpCharOp> {
+public:
+ using mlir::OpRewritePattern<hlfir::CmpCharOp>::OpRewritePattern;
+
+ llvm::LogicalResult
+ matchAndRewrite(hlfir::CmpCharOp cmp,
+ mlir::PatternRewriter &rewriter) const override {
+
+ fir::FirOpBuilder builder{rewriter, cmp.getOperation()};
+ const mlir::Location &loc = cmp->getLoc();
+
+ auto toVariable =
+ [&builder,
+ &loc](mlir::Value val) -> std::pair<mlir::Value, hlfir::AssociateOp> {
+ mlir::Value opnd;
+ hlfir::AssociateOp associate;
+ if (mlir::isa<hlfir::ExprType>(val.getType())) {
+ hlfir::Entity entity{val};
+ mlir::NamedAttribute byRefAttr = fir::getAdaptToByRefAttr(builder);
+ associate = hlfir::genAssociateExpr(loc, builder, entity,
+ entity.getType(), "", byRefAttr);
+ opnd = associate.getBase();
+ } else {
+ opnd = val;
+ }
+ return {opnd, associate};
+ };
+
+ auto [lhsOpnd, lhsAssociate] = toVariable(cmp.getLchr());
+ auto [rhsOpnd, rhsAssociate] = toVariable(cmp.getRchr());
+
+ hlfir::Entity lhs{lhsOpnd};
+ hlfir::Entity rhs{rhsOpnd};
+
+ auto charTy = mlir::cast<fir::CharacterType>(lhs.getFortranElementType());
+ unsigned kind = charTy.getFKind();
+
+ auto bits = builder.getKindMap().getCharacterBitsize(kind);
+ auto intTy = builder.getIntegerType(bits);
+
+ auto idxTy = builder.getIndexType();
+ auto charLen1Ty =
+ fir::CharacterType::getSingleton(builder.getContext(), kind);
+ mlir::Type designatorType =
+ fir::ReferenceType::get(charLen1Ty, fir::isa_volatile_type(charTy));
+ auto idxAttr = builder.getIntegerAttr(idxTy, 0);
+
+ auto genExtractAndConvertToInt =
+ [&idxAttr, &intTy, &designatorType](
+ mlir::Location loc, fir::FirOpBuilder &builder,
+ hlfir::Entity &charStr, mlir::Value index, mlir::Value length) {
+ auto singleChr = hlfir::DesignateOp::create(
+ builder, loc, designatorType, charStr, /*component=*/{},
+ /*compShape=*/mlir::Value{}, hlfir::DesignateOp::Subscripts{},
+ /*substring=*/mlir::ValueRange{index, index},
+ /*complexPart=*/std::nullopt,
+ /*shape=*/mlir::Value{}, /*typeParams=*/mlir::ValueRange{length},
+ fir::FortranVariableFlagsAttr{});
+ auto chrVal = fir::LoadOp::create(builder, loc, singleChr);
+ mlir::Value intVal = fir::ExtractValueOp::create(
+ builder, loc, intTy, chrVal, builder.getArrayAttr(idxAttr));
+ return intVal;
+ };
+
+ mlir::arith::CmpIPredicate predicate = cmp.getPredicate();
+ mlir::Value oneIdx = builder.createIntegerConstant(loc, idxTy, 1);
+
+ mlir::Value lhsLen = builder.createConvert(
+ loc, idxTy, hlfir::genCharLength(loc, builder, lhs));
+ mlir::Value rhsLen = builder.createConvert(
+ loc, idxTy, hlfir::genCharLength(loc, builder, rhs));
+
+ enum class GenCmp { LeftToRight, LeftToBlank, BlankToRight };
+
+ mlir::Value zeroInt = builder.createIntegerConstant(loc, intTy, 0);
+ mlir::Value oneInt = builder.createIntegerConstant(loc, intTy, 1);
+ mlir::Value negOneInt = builder.createIntegerConstant(loc, intTy, -1);
+ mlir::Value blankInt = builder.createIntegerConstant(loc, intTy, ' ');
+
+ auto step = GenCmp::LeftToRight;
+ auto genCmp =
+ [&](mlir::Location loc, fir::FirOpBuilder &builder,
+ mlir::ValueRange index,
+ mlir::ValueRange reduxrgs) -> llvm::SmallVector<mlir::Value, 1> {
+ assert(index.size() == 1 && "expected single loop");
+ assert(reduxrgs.size() == 1 && "expected single reduction value");
+ mlir::Value inRes = reduxrgs[0];
+ auto accEQzero = mlir::arith::CmpIOp::create(
+ builder, loc, mlir::arith::CmpIPredicate::eq, inRes, zeroInt);
+
+ mlir::Value res =
+ builder
+ .genIfOp(loc, {intTy}, accEQzero,
+ /*withElseRegion=*/true)
+ .genThen([&]() {
+ mlir::Value offset =
+ builder.createConvert(loc, idxTy, index[0]);
+ mlir::Value lhsInt;
+ mlir::Value rhsInt;
+ if (step == GenCmp::LeftToRight) {
+ lhsInt = genExtractAndConvertToInt(loc, builder, lhs, offset,
+ oneIdx);
+ rhsInt = genExtractAndConvertToInt(loc, builder, rhs, offset,
+ oneIdx);
+ } else if (step == GenCmp::LeftToBlank) {
+ // lhsLen > rhsLen
+ offset =
+ mlir::arith::AddIOp::create(builder, loc, rhsLen, offset);
+
+ lhsInt = genExtractAndConvertToInt(loc, builder, lhs, offset,
+ oneIdx);
+ rhsInt = blankInt;
+ } else if (step == GenCmp::BlankToRight) {
+ // rhsLen > lhsLen
+ offset =
+ mlir::arith::AddIOp::create(builder, loc, lhsLen, offset);
+
+ lhsInt = blankInt;
+ rhsInt = genExtractAndConvertToInt(loc, builder, rhs, offset,
+ oneIdx);
+ } else {
+ llvm_unreachable(
+ "unknown compare step for CmpCharOp lowering");
+ }
+
+ mlir::Value newVal = mlir::arith::SelectOp::create(
+ builder, loc,
+ mlir::arith::CmpIOp::create(builder, loc,
+ mlir::arith::CmpIPredicate::ult,
+ lhsInt, rhsInt),
+ negOneInt, inRes);
+ newVal = mlir::arith::SelectOp::create(
+ builder, loc,
+ mlir::arith::CmpIOp::create(builder, loc,
+ mlir::arith::CmpIPredicate::ugt,
+ lhsInt, rhsInt),
+ oneInt, newVal);
+ fir::ResultOp::create(builder, loc, newVal);
+ })
+ .genElse([&]() { fir::ResultOp::create(builder, loc, inRes); })
+ .getResults()[0];
+
+ return {res};
+ };
+
+ // First generate comparison of two strings for the legth of the shorter
+ // one.
+ mlir::Value minLen = mlir::arith::SelectOp::create(
+ builder, loc,
+ mlir::arith::CmpIOp::create(
+ builder, loc, mlir::arith::CmpIPredicate::slt, lhsLen, rhsLen),
+ lhsLen, rhsLen);
+
+ llvm::SmallVector<mlir::Value, 1> loopOut =
+ hlfir::genLoopNestWithReductions(loc, builder, {minLen},
+ /*reductionInits=*/{zeroInt}, genCmp,
+ /*isUnordered=*/false);
+ mlir::Value partRes = loopOut[0];
+
+ auto lhsLonger = mlir::arith::CmpIOp::create(
+ builder, loc, mlir::arith::CmpIPredicate::sgt, lhsLen, rhsLen);
+ mlir::Value tempRes =
+ builder
+ .genIfOp(loc, {intTy}, lhsLonger,
+ /*withElseRegion=*/true)
+ .genThen([&]() {
+ // If left is the longer string generate compare left to blank.
+ step = GenCmp::LeftToBlank;
+ auto lenDiff =
+ mlir::arith::SubIOp::create(builder, loc, lhsLen, rhsLen);
+
+ llvm::SmallVector<mlir::Value, 1> output =
+ hlfir::genLoopNestWithReductions(loc, builder, {lenDiff},
+ /*reductionInits=*/{partRes},
+ genCmp,
+ /*isUnordered=*/false);
+ mlir::Value res = output[0];
+ fir::ResultOp::create(builder, loc, res);
+ })
+ .genElse([&]() {
+ // If right is the longer string generate compare blank to
+ // right.
+ step = GenCmp::BlankToRight;
+ auto lenDiff =
+ mlir::arith::SubIOp::create(builder, loc, rhsLen, lhsLen);
+ llvm::SmallVector<mlir::Value, 1> output =
+ hlfir::genLoopNestWithReductions(loc, builder, {lenDiff},
+ /*reductionInits=*/{partRes},
+ genCmp,
+ /*isUnordered=*/false);
+
+ mlir::Value res = output[0];
+ fir::ResultOp::create(builder, loc, res);
+ })
+ .getResults()[0];
+ if (lhsAssociate)
+ hlfir::EndAssociateOp::create(builder, loc, lhsAssociate);
+ if (rhsAssociate)
+ hlfir::EndAssociateOp::create(builder, loc, rhsAssociate);
+
+ auto finalCmpResult =
+ mlir::arith::CmpIOp::create(builder, loc, predicate, tempRes, zeroInt);
+ rewriter.replaceOp(cmp, finalCmpResult);
+ return mlir::success();
+ }
+};
+
template <typename Op>
class MatmulConversion : public mlir::OpRewritePattern<Op> {
public:
@@ -2748,8 +2955,8 @@ class SimplifyHLFIRIntrinsics
patterns.insert<ReductionConversion<hlfir::SumOp>>(context);
patterns.insert<ArrayShiftConversion<hlfir::CShiftOp>>(context);
patterns.insert<ArrayShiftConversion<hlfir::EOShiftOp>>(context);
+ patterns.insert<CmpCharOpConversion>(context);
patterns.insert<MatmulConversion<hlfir::MatmulTransposeOp>>(context);
-
patterns.insert<ReductionConversion<hlfir::CountOp>>(context);
patterns.insert<ReductionConversion<hlfir::AnyOp>>(context);
patterns.insert<ReductionConversion<hlfir::AllOp>>(context);
diff --git a/flang/test/HLFIR/invalid.fir b/flang/test/HLFIR/invalid.fir
index 0f54a0250294b..b4baedb1e6477 100644
--- a/flang/test/HLFIR/invalid.fir
+++ b/flang/test/HLFIR/invalid.fir
@@ -296,6 +296,17 @@ func.func @bad_concat_4(%arg0: !fir.ref<!fir.char<1,30>>) {
return
}
+// -----
+func.func @bad_cmpchar_1(%arg0: !fir.ref<!fir.char<1,10>>, %arg1: !fir.ref<!fir.char<2,10>>) {
+ // expected-error at +1 {{'hlfir.cmpchar' op character arguments must have the same KIND}}
+ %0 = hlfir.cmpchar ne %arg0 %arg1 : (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<2,10>>) -> i1
+}
+
+func.func @bad_cmpchar_2(%arg0: !fir.ref<!fir.char<1,10>>, %arg1: !fir.ref<!fir.char<1,10>>) {
+ // expected-error at +1 {{'hlfir.cmpchar' op expected signed predicate}}
+ %0 = hlfir.cmpchar ugt %arg0 %arg1 : (!fir.ref<!fir.char<1,10>>, !fir.ref<!fir.char<1,10>>) -> i1
+}
+
// -----
func.func @bad_any1(%arg0: !hlfir.expr<?x!fir.logical<4>>) {
// expected-error at +1 {{'hlfir.any' op result must have the same element type as MASK argument}}
diff --git a/flang/test/HLFIR/simplify-hlfir-intrinsics-cmpchar-scalar.fir b/flang/test/HLFIR/simplify-hlfir-intrinsics-cmpchar-scalar.fir
new file mode 100644
index 0000000000000..864d50723bc17
--- /dev/null
+++ b/flang/test/HLFIR/simplify-hlfir-intrinsics-cmpchar-scalar.fir
@@ -0,0 +1,610 @@
+// RUN: fir-opt %s --simplify-hlfir-intrinsics | FileCheck %s
+
+
+// function test_eq(x, y)
+// logical :: test_eq
+// character(len=*,kind=1) :: x, y
+// test_eq = x .eq. y
+// end function test_eq
+ func.func @_QPtest_eq(%arg0: !fir.boxchar<1> {fir.bindc_name = "x"}, %arg1: !fir.boxchar<1> {fir.bindc_name = "y"}) -> !fir.logical<4> {
+// CHECK-LABEL: func.func @_QPtest_eq(
+// CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"},
+// CHECK-SAME: %[[ARG1:.*]]: !fir.boxchar<1> {fir.bindc_name = "y"}) -> !fir.logical<4> {
+// CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope
+// CHECK: %[[VAL_6:.*]] = fir.alloca !fir.logical<4> {bindc_name = "test_eq", uniq_name = "_QFtest_eqEtest_eq"}
+// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFtest_eqEtest_eq"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+// CHECK: %[[VAL_8:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]]#0 typeparams %[[VAL_8]]#1 dummy_scope %[[VAL_5]] {uniq_name = "_QFtest_eqEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+// CHECK: %[[VAL_10:.*]]:2 = fir.unboxchar %[[ARG1]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+// CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]]#0 typeparams %[[VAL_10]]#1 dummy_scope %[[VAL_5]] {uniq_name = "_QFtest_eqEy"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+ %0 = fir.dummy_scope : !fir.dscope
+ %1 = fir.alloca !fir.logical<4> {bindc_name = "test_eq", uniq_name = "_QFtest_eqEtest_eq"}
+ %2:2 = hlfir.declare %1 {uniq_name = "_QFtest_eqEtest_eq"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+ %3:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+ %4:2 = hlfir.declare %3#0 typeparams %3#1 dummy_scope %0 {uniq_name = "_QFtest_eqEx"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+ %5:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+ %6:2 = hlfir.declare %5#0 typeparams %5#1 dummy_scope %0 {uniq_name = "_QFtest_eqEy"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>)
+ %7 = hlfir.cmpchar eq %4#0 %6#0 : (!fir.boxchar<1>, !fir.boxchar<1>) -> i1
+// CHECK: %[[VAL_12:.*]] = arith.cmpi slt, %[[VAL_8]]#1, %[[VAL_10]]#1 : index
+// CHECK: %[[VAL_13:.*]] = arith.select %[[VAL_12]], %[[VAL_8]]#1, %[[VAL_10]]#1 : index
+// CHECK: %[[VAL_14:.*]] = fir.do_loop %[[VAL_15:.*]] = %c1 to %[[VAL_13]] step %c1 iter_args(%[[VAL_16:.*]] = %c0_i8) -> (i8) {
+// CHECK: %[[VAL_17:.*]] = arith.cmpi eq, %[[VAL_16]], %c0_i8 : i8
+// CHECK: %[[VAL_18:.*]] = fir.if %[[VAL_17]] -> (i8) {
+// CHECK: %[[VAL_19:.*]] = hlfir.designate %[[VAL_9]]#0 substr %[[VAL_15]], %[[VAL_15]] typeparams %c1 : (!fir.boxchar<1>, index, index, index) -> !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_20:.*]] = fir.load %[[VAL_19]] : !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_21:.*]] = fir.extract_value %[[VAL_20]], [0 : index] : (!fir.char<1>) -> i8
+// CHECK: %[[VAL_22:.*]] = hlfir.designate %[[VAL_11]]#0 substr %[[VAL_15]], %[[VAL_15]] typeparams %c1 : (!fir.boxchar<1>, index, index, index) -> !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_23:.*]] = fir.load %[[VAL_22]] : !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_24:.*]] = fir.extract_value %[[VAL_23]], [0 : index] : (!fir.char<1>) -> i8
+// CHECK: %[[VAL_25:.*]] = arith.cmpi ult, %[[VAL_21]], %[[VAL_24]] : i8
+// CHECK: %[[VAL_26:.*]] = arith.select %[[VAL_25]], %c-1_i8, %[[VAL_16]] : i8
+// CHECK: %[[VAL_27:.*]] = arith.cmpi ugt, %[[VAL_21]], %[[VAL_24]] : i8
+// CHECK: %[[VAL_28:.*]] = arith.select %[[VAL_27]], %c1_i8, %[[VAL_26]] : i8
+// CHECK: fir.result %[[VAL_28]] : i8
+// CHECK: } else {
+// CHECK: fir.result %[[VAL_16]] : i8
+// CHECK: }
+// CHECK: fir.result %[[VAL_18]] : i8
+// CHECK: }
+// CHECK: %[[VAL_29:.*]] = arith.cmpi sgt, %[[VAL_8]]#1, %[[VAL_10]]#1 : index
+// CHECK: %[[VAL_30:.*]] = fir.if %[[VAL_29]] -> (i8) {
+// CHECK: %[[VAL_31:.*]] = arith.subi %[[VAL_8]]#1, %[[VAL_10]]#1 : index
+// CHECK: %[[VAL_32:.*]] = fir.do_loop %[[VAL_33:.*]] = %c1 to %[[VAL_31]] step %c1 iter_args(%[[VAL_34:.*]] = %[[VAL_14]]) -> (i8) {
+// CHECK: %[[VAL_35:.*]] = arith.cmpi eq, %[[VAL_34]], %c0_i8 : i8
+// CHECK: %[[VAL_36:.*]] = fir.if %[[VAL_35]] -> (i8) {
+// CHECK: %[[VAL_37:.*]] = arith.addi %[[VAL_10]]#1, %[[VAL_33]] : index
+// CHECK: %[[VAL_38:.*]] = hlfir.designate %[[VAL_9]]#0 substr %[[VAL_37]], %[[VAL_37]] typeparams %c1 : (!fir.boxchar<1>, index, index, index) -> !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_39:.*]] = fir.load %[[VAL_38]] : !fir.ref<!fir.char<1>>
+// CHECK: %[[VAL_40:.*]] = fir.extract_value %[[VAL_39]], [0 : index] : (!fir.char<1>) -> i8
+// CHECK: %[[VAL_41:.*]] = arith.cmpi ult, %[[VAL_40]], %c32_i8 : i8
+// CHECK: %[[VAL_42:.*]] = arith.select %[[VAL_41]], %c-1_i8, %[[VAL_34]] : i8
+// CHECK: %[[VAL_43:.*]] = arith.cmpi ugt, %[[VAL_40]], %c32_i8 : i8
+// CHECK: %[[VAL_44:.*]] = arith.select %[[VAL_43]], %c1_i8, %[[VAL_42]] : i8
+// CHECK: fir.result %[[VAL_44]] : i8
+// CHECK: } else {
+// CHECK: fir.result %[[VAL_34]] : i8
+// CHECK: }
+// CHECK: fir.result %[[VAL_36]] : i8
+// CHECK: }
+/...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/155461
More information about the flang-commits
mailing list