[flang-commits] [flang] [flang] Add definition of hlfir.cmpchar operation. (PR #155457)

Valery Dmitriev via flang-commits flang-commits at lists.llvm.org
Wed Aug 27 08:05:47 PDT 2025


https://github.com/valerydmit updated https://github.com/llvm/llvm-project/pull/155457

>From 1cc86d5d62a1142032cead698d9656b7dbf08017 Mon Sep 17 00:00:00 2001
From: Valery Dmitriev <valeryd at nvidia.com>
Date: Tue, 26 Aug 2025 09:46:46 -0700
Subject: [PATCH 1/2] [flang] Add definition of hlfir.cmpchar operation.

Fortran character comparison now lowered early into a runtime call.
It is going to be lowered into the operation, so that later it could
be optimized as inline code or end up into a runtime call.
---
 .../include/flang/Optimizer/HLFIR/HLFIROps.td | 20 +++++++++++
 flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp     | 34 +++++++++++++++++++
 flang/test/HLFIR/invalid.fir                  | 11 ++++++
 3 files changed, 65 insertions(+)

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/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}}

>From fb33634e9b78e2a56050cc96a9a807719d838d4d Mon Sep 17 00:00:00 2001
From: Valery Dmitriev <valeryd at nvidia.com>
Date: Wed, 27 Aug 2025 08:05:11 -0700
Subject: [PATCH 2/2] Add fallthrough annotations

---
 flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 964d183631186..79d1ebc81990b 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -834,10 +834,15 @@ llvm::LogicalResult hlfir::CmpCharOp::verify() {
 
   switch (getPredicate()) {
   case mlir::arith::CmpIPredicate::slt:
+    [[fallthrough]];
   case mlir::arith::CmpIPredicate::sle:
+    [[fallthrough]];
   case mlir::arith::CmpIPredicate::eq:
+    [[fallthrough]];
   case mlir::arith::CmpIPredicate::ne:
+    [[fallthrough]];
   case mlir::arith::CmpIPredicate::sgt:
+    [[fallthrough]];
   case mlir::arith::CmpIPredicate::sge:
     break;
   default:



More information about the flang-commits mailing list