[flang-commits] [flang] [flang] Simplify the comparison of characters (PR #154593)

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Tue Sep 23 08:08:30 PDT 2025


================
@@ -0,0 +1,127 @@
+//===- ExpressionSimplification.cpp - Simplify HLFIR expressions ----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Optimizer/HLFIR/Passes.h"
+#include "llvm/Support/DebugLog.h"
+
+namespace hlfir {
+#define GEN_PASS_DEF_EXPRESSIONSIMPLIFICATION
+#include "flang/Optimizer/HLFIR/Passes.h.inc"
+} // namespace hlfir
+
+#define DEBUG_TYPE "expression-simplification"
+
+static void removeOp(mlir::Operation *op) {
+  op->dropAllReferences();
+  op->dropAllUses();
+  op->erase();
+}
+
+// Get the first user of `op`.
+// Note that we consider the first user to be the one on the lowest line of
+// the emitted HLFIR. The user iterator considers the opposite.
+template <typename UserOp>
+static UserOp getFirstUser(mlir::Operation *op) {
+  auto it = op->user_begin(), end = op->user_end(), prev = it;
+  for (; it != end; prev = it++)
+    ;
+  if (prev != end)
+    if (auto userOp = mlir::dyn_cast<UserOp>(*prev))
+      return userOp;
+  return {};
+}
+
+// Get the last user of `op`.
+// Note that we consider the last user to be the one on the highest line of
+// the emitted HLFIR. The user iterator considers the opposite.
+template <typename UserOp>
+static UserOp getLastUser(mlir::Operation *op) {
+  if (!op->getUsers().empty())
+    if (auto userOp = mlir::dyn_cast<UserOp>(*op->user_begin()))
+      return userOp;
+  return {};
+}
+
+namespace {
+
+// This class analyzes a trimmed character and removes the trim operation if
+// its result is not used elsewhere.
+class TrimRemover {
+public:
+  TrimRemover(mlir::Value charVal) : charVal(charVal) {}
+  TrimRemover(const TrimRemover &) = delete;
+
+  bool charWasTrimmed();
+  void removeTrim();
+
+private:
+  mlir::Value charVal;
+  hlfir::CharTrimOp trimOp;
+  hlfir::CmpCharOp cmpCharOp;
+  hlfir::DestroyOp destroyOp;
+};
+
+bool TrimRemover::charWasTrimmed() {
+  LDBG() << "charWasTrimmed: " << charVal;
+
+  trimOp = mlir::dyn_cast<hlfir::CharTrimOp>(charVal.getDefiningOp());
+  if (!trimOp)
+    return false;
+  int trimUses = std::distance(trimOp->use_begin(), trimOp->use_end());
+  cmpCharOp = getFirstUser<hlfir::CmpCharOp>(trimOp);
+  destroyOp = getLastUser<hlfir::DestroyOp>(trimOp);
+  return cmpCharOp && destroyOp && trimUses == 2;
+}
+
+void TrimRemover::removeTrim() {
+  LDBG() << "removeTrim: " << trimOp;
+
+  cmpCharOp->replaceUsesOfWith(trimOp.getResult(), trimOp.getChr());
+  removeOp(destroyOp);
+  removeOp(trimOp);
+}
+
+class ExpressionSimplification
+    : public hlfir::impl::ExpressionSimplificationBase<
+          ExpressionSimplification> {
+public:
+  using ExpressionSimplificationBase<
+      ExpressionSimplification>::ExpressionSimplificationBase;
+
+  void runOnOperation() override;
+
+private:
+  // Simplify character comparisons.
+  // Because character comparison appends spaces to the shorter character,
+  // calls to trim() that are used only in the comparison can be eliminated.
+  //
+  // Example:
+  // `trim(x) == trim(y)`
+  // can be simplified to
+  // `x == y`
+  void simplifyCmpChar(hlfir::CmpCharOp cmpChar);
+};
+
+void ExpressionSimplification::simplifyCmpChar(hlfir::CmpCharOp cmpChar) {
+  TrimRemover lhsTrimRem(cmpChar.getLchr());
+  TrimRemover rhsTrimRem(cmpChar.getRchr());
+
+  if (lhsTrimRem.charWasTrimmed())
+    lhsTrimRem.removeTrim();
+  if (rhsTrimRem.charWasTrimmed())
+    rhsTrimRem.removeTrim();
+}
+
+void ExpressionSimplification::runOnOperation() {
+  mlir::ModuleOp module = getOperation();
+  module.walk([&](hlfir::CmpCharOp cmpChar) { simplifyCmpChar(cmpChar); });
----------------
vzakhari wrote:

Sorry, I missed the notification. I will review now.

https://github.com/llvm/llvm-project/pull/154593


More information about the flang-commits mailing list